home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tjgold.zip / INSTALL.002 / GOLDWIN.PAS < prev    next >
Pascal/Delphi Source File  |  1995-07-12  |  81KB  |  2,664 lines

  1. {--------------------------------------------------------------------------}
  2. {                Product: TechnoJock's Turbo Toolkit                       }
  3. {                Version: GOLD                                             }
  4. {                Build:   1.01                                             }
  5. {                                                                          }
  6. {                Copyright 1986-1995  TechnoJock Software, Inc.            }
  7. {                           All Rights Reserved                            }
  8. {                          Restricted by License                           }
  9. {--------------------------------------------------------------------------}
  10.  
  11.                      {********************************}
  12.                      {**      Unit:   GOLDWIN       **}
  13.                      {********************************}
  14.  
  15. {++++++++++++++++++++++++++++++} unit GOLDWIN; {++++++++++++++++++++++++++++}
  16.  
  17. {$I GOLDFLAG.INC}
  18. {$IFNDEF GOLDWIN}
  19.    {$DEFINE GOLDWIN}
  20. {$ENDIF}
  21.  
  22. {++++++++++++++++++++++++++++++++} INTERFACE {+++++++++++++++++++++++++++++++}
  23.  
  24. uses DOS, CRT,
  25.      GoldAttr, GoldHard, GoldTint, GoldMisc,
  26.      GoldLink, GoldKey, GoldFast, GoldStr;
  27.  
  28. const
  29.    MaxWindows = 10;          {Change this constant as necessary}
  30.  
  31. type
  32.    WinType         = (WPlain, WClose, WMove, WMoveNoClose, WStretch);
  33.    DeskWinNumState = (WNoNumbers,WShowNumbers,WUseDefaults);
  34.    WindowPtr = ^WindowImage;
  35.    WindowImage = record
  36.       ScreenPtr: Pointer;     {pointer to screen data}
  37.       Coord    : gByteCoords; {window coords}
  38.       CursorX  : byte;        {cursor location}
  39.       CursorY  : byte;
  40.       ScanTop  : byte;        {cursor shape}
  41.       ScanBot  : byte;
  42.    end;
  43.  
  44.    {button structure}
  45.    ButtonZone = record
  46.      X1,X2: byte;
  47.      ButtonFace: StrButton;
  48.    end;
  49.  
  50.    ThreeButs = array [1..3] of ButtonZone;
  51.  
  52.    WinSet = record
  53.       LastECode: integer;
  54.       EMsgFunc: ErrMsgFunc;
  55.       FirstWin: WStructurePtr; {structure declared in GOLDFAST}
  56.       TopWin: WStructurePtr;
  57.       RotateKey: word;         {key to switch to next window in list}
  58.       CloseKey: word;          {key to close the window}
  59.       MoveKey: word;           {key to invoke manual window move}
  60.       ZoomKey:word;            {keycode for zoom}
  61.       StretchKey:word;         {keycode for manual stretch}
  62.       PromptStyle: byte;       {window style for ad-hoc messages}
  63.       DesktopFadeStyle: byte;  {window style when not top window}
  64.       DesktopFocusStyle: byte; {window style when of top window on desktop}
  65.       DesktopActive: boolean;
  66.       DesktopNums: DeskWinNumState;  {should Desktop windows show numbers}
  67.       DesktopCascadeNew: boolean;    {should new windows be placed down-left of prev}
  68.       {defaults for new windows}
  69.       WinState: byte;
  70.       Boundary: gCoords;       {max area in which window can move}
  71.       Scroll: ScrollType;      {are scroll bars supported}
  72.       MinWidth: byte;          {min width of SmartWin}
  73.       MinDepth: byte;          {min depth of SmartWin}
  74.       {window icons}
  75.       WinCloseChar: char;
  76.       WinCloseCharDown: char;
  77.       WinZoomMaxChar: char;
  78.       WinZoomBackChar: char;
  79.       {move message}
  80.       WinMoveMsgPart1:string[40];
  81.       WinMoveMsgPart2:string[30];
  82.       {buttons}
  83.       OKButStr: strButton;
  84.       OKHotKey: word;
  85.       CancelButStr: strButton;
  86.       CancelHotKey: word;
  87.       YesButStr: strButton;
  88.       YesHotKey: word;
  89.       NoButStr: strButton;
  90.       NoHotKey: word;
  91.       HelpButStr: strButton;
  92.       HelpHotKey: word;
  93.    end; {WinSet}
  94.  
  95. const
  96.     {bit positions for WinState settings}
  97.     WinAllowClose    = 0;   {is close icon active}
  98.     WinAllowMove     = 1;   {can window be moved}
  99.     WinShowNum       = 2;   {display window number in border}
  100.     WinAllowStretch  = 3;   {is user allowed to stretch}
  101.     WinSmartStretch  = 4;   {is there a callback function for the stretch}
  102.     WinZoomed        = 5;   {is the window zoomed}
  103.     (* Following defined in GOLDFAST
  104.     WinConfine       = 6;   {restrict screen writes to WX1..WY2}
  105.     *)
  106.     DeskTileKey      = 1000;
  107.     DeskCascadeKey   = 1001;
  108.  
  109. var
  110.    {old style windows}
  111.    Win: array[1..MaxWindows] of WindowPtr;
  112.    {Gold Windows}
  113.    WinVars: WinSet;
  114.  
  115. {misc procs}
  116. function  LastWinError: integer;
  117. procedure NoStretchHook(X1,Y1,X2,Y2:byte);
  118. procedure NoKeyHandler;
  119.  function BasicCloseHandler(Handle: integer): boolean;
  120. procedure BasicFocusHandler(Handle: integer);
  121. {the old TTT5 routines for backward compatibility}
  122. procedure Mkwin(x1,y1,x2,y2,FB,boxtype:integer);
  123. procedure GrowMkwin(x1,y1,x2,y2,FB,boxtype:integer);
  124. procedure Rmwin;
  125. {Gold Windows}
  126. procedure ActivateWindow(Win:word);
  127. procedure ActivateTopWindow;
  128. function  WindowHasFocus: boolean;
  129. function  WinCount:integer;
  130. function  WinPtr(WinNum:integer):WStructurePtr;
  131. function  WinCreate(X1,Y1,X2,Y2:integer;Style:byte): integer; {returns window handle}
  132. procedure WinSetPosition(Win:integer;NewX,NewY:shortint);
  133. procedure WinSetMinSize(Win:integer;Width,Depth: byte);
  134. procedure WinSetType(Win:integer;W:WinType);
  135. procedure WinSetScrollType(Win:integer;S:ScrollType);
  136. procedure WinSetColor(Win:integer; A:TintElement;C:byte);
  137. procedure WinSetShowNum(Win:integer;On:boolean);
  138. procedure WinSetTitle(Win:integer;Tit:string);
  139. procedure WinSetStretchProc(Win:integer;S:StretchProc);
  140. procedure WinSetFrame(Win:integer;Bright:boolean);
  141. procedure WinDisplay(Win:integer);
  142. procedure WinDispose(Win:integer);
  143. {Scroll bar borders}
  144. procedure DrawHorizBar(WinId:integer;Current,Max: longint);
  145. procedure DrawVertBar(WinId:integer;Current,Max: longint);
  146. {focus/desktop management}
  147. procedure WinFadeTopWin;
  148. procedure WinFocusTopWin;
  149. procedure WinChangeFocus(WinId:integer);
  150. function  WinWithFocus:integer;
  151. procedure WinShiftFocus;
  152. procedure DeskNextWinCoords(var TLX,TLY: byte);
  153. {key management functions}
  154. function  IsWinKey(K:word;KX,KY:integer):boolean;
  155. function  IsFocusKey(K:word;KX,KY:Integer):byte;
  156. procedure WinProcessKey(var K:word; var KX,KY:byte);
  157. function  WinGlobalX(WinId:integer;X1:byte):byte;
  158. function  WinLocalX(WinId:integer;X1:byte):byte;
  159. function  WinGlobalY(WinId:integer;Y1:byte):byte;
  160. function  WinLocalY(WinId:integer;Y1:byte):byte;
  161. {message displaying procs}
  162. procedure TempMessageCh(X,Y,FB:integer;St:strscreen;var Ch : char);procedure TempMessage(X,Y,FB:integer;St:strscreen);
  163. procedure TempMessageBoxCh(X1,Y1,FB,BoxType:integer;St:strscreen;var Ch : char);
  164. procedure TempMessageBox(X1,Y1,FB,BoxType:integer;St:strscreen);
  165. {Prompt Dialogs}
  166. procedure PromptOK(Tit,Str:string);
  167. function  PromptOKCancel(Tit,Str:string): byte;
  168. function  PromptYesNo(Tit,Str:string): byte;
  169. function  PromptCustom(Tit,Str:string; But1,But2,But3:StrButton; HK1,HK2,HK3,Default:word; WaitTime:longint): byte;
  170. procedure PromptOKStrLL(Tit:string;StrLL:StringLL);
  171. function  PromptOKCancelStrLL(Tit:string;StrLL:StringLL): byte;
  172. function  PromptYesNoStrLL(Tit:string;StrLL:StringLL): byte;
  173. function  PromptCustomStrLL(Tit:string; StrLL:StringLL; But1,But2,But3:StrButton;
  174.                       HK1,HK2,HK3,Default:word; WaitTime:longint): byte;
  175.  
  176. {dragging}
  177. procedure DragItem(var X1,Y1,X2,Y2:byte;DragAttr:byte;UsingMouse:boolean;Fillch:char;FillAttr:byte);
  178. {general}
  179. procedure WinDefaultSettings;
  180. procedure GoldWinInit;
  181. {internal}
  182. procedure MkPopUpWin(var x1,y1,x2,y2:integer; FB1,FB2,style:byte);
  183. procedure WinPaint(Win:integer);
  184. procedure CreateWin(x1,y1,x2,y2:integer);
  185. function  PrevWinInChain(WCP:WStructurePtr): WStructurePtr;
  186. procedure WinStretch(UsingMouse:boolean;OldX,OldY:byte);
  187. procedure WinPostStretch(X1,Y1,X2,Y2: integer);
  188.  
  189.  
  190.  
  191. {+++++++++++++++++++++++++++++} IMPLEMENTATION {+++++++++++++++++++++++++++++}
  192. CONST
  193.    TopWin = 0;
  194.    WindowCounter: byte = 0;
  195.  
  196.                       {******************************}
  197.                       {**  Miscellaneous Routines  **}
  198.                       {******************************}
  199. {$IFOPT F-}
  200.    {$DEFINE FOFF}
  201.    {$F+}
  202. {$ENDIF}
  203. function WinEMsg(ECode:integer): string;
  204. {}
  205. begin
  206.    case Ecode of
  207.       0: exit;
  208.       else
  209.          WinEMsg := 'Internal Window error';
  210.    end; {case}
  211. end; { WinEMsg }
  212. {$IFDEF FOFF}
  213.    {$F-}
  214.    {$UNDEF FOFF}
  215. {$ENDIF}
  216.  
  217. procedure WinSetError(ECode:integer);
  218. {}
  219. {$IFOPT D+}
  220. var Msg: string;
  221. {$ENDIF}
  222. begin
  223.    WinVars.LastEcode := ECode;
  224. {$IFOPT D+}  {if debug active display an error message and terminate}
  225.    if Ecode <> 0 then
  226.    begin
  227.       str(Ecode,Msg);
  228.       Msg := Msg+': '+WinVars.EMsgFunc(Ecode);
  229.       SetWinIgnore(true);
  230.       if PromptCustom(' GoldWin Error ',Msg,' ~I~gnore ',' ~A~bort ','',279,286,0,0, 10000) = 2 then
  231.          Halt;
  232.    end;
  233. {$ENDIF}
  234. end; {WinSetError}
  235.  
  236. function LastWinError: integer;
  237. {}
  238. begin
  239.    LastWinError := WinVars.LastECode;
  240. end; { LastWinError }
  241.  
  242. {$IFOPT F-}
  243.    {$DEFINE FOFF}
  244.    {$F+}
  245. {$ENDIF}
  246.  
  247.  procedure NoStretchHook(X1,Y1,X2,Y2:byte);
  248.  {empty proc}
  249.  begin end; {NoStretchHook}
  250.  
  251.  procedure NoKeyHandler;
  252.  {empty proc}
  253.  begin end; {NoKeyHandler}
  254.  
  255.  function BasicCloseHandler(Handle: integer): boolean;
  256.  {}
  257.  begin
  258.     WinDispose(Handle);
  259.     BasicCloseHandler := true;
  260.  end; {BasicCloseHandler}
  261.  
  262.  procedure BasicFocusHandler(Handle: integer);
  263.  {empty proc}
  264.  begin end; {BasicFocusHandler}
  265.  
  266. {$IFDEF FOFF}
  267.    {$F-}
  268.    {$UNDEF FOFF}
  269. {$ENDIF}
  270.  
  271.                    {***********************************}
  272.                    {**  Traditional Window Routines  **}
  273.                    {***********************************}
  274.  
  275. procedure VerifyWindowOnScreen(var x1,y1,x2,y2:integer);
  276. {INTERNAL}
  277. var Delta: integer;
  278. begin
  279.    if X1 < 1 then
  280.    begin
  281.       inc(X2,succ(abs(X1)));
  282.       inc(X1,succ(abs(X1)));
  283.    end else if X2 > HardVars.Width then
  284.    begin
  285.       Delta := X2 - HardVars.Width;
  286.       dec(X2,Delta);
  287.       dec(X1,Delta);
  288.    end;
  289.    if X1 < 1 then
  290.       X1 := 1;
  291.    if X2 > HardVars.Width then
  292.       X2 := HardVars.Width;
  293.    {Now the Y coords}
  294.    if Y1 < 1 then
  295.    begin
  296.       inc(Y2,succ(abs(Y1)));
  297.       inc(Y1,succ(abs(Y1)));
  298.    end else if Y2 > HardVars.Depth then
  299.    begin
  300.       Delta := Y2 - HardVars.Depth;
  301.       dec(Y2,Delta);
  302.       dec(Y1,Delta);
  303.    end;
  304.    if Y1 < 1 then
  305.       Y1 := 1;
  306.    if Y2 > HardVars.Depth then
  307.       Y2 := HardVars.Depth;
  308. end; { VerifyWindowOnScreen }
  309.  
  310. procedure CreateWin(x1,y1,x2,y2:integer);
  311. {INTERNAL - called by MkWin and GrowMkWin}
  312. begin
  313.    if GoldMaxAvail >= sizeOf(Win[WindowCounter]^) then
  314.    begin
  315.       inc(WindowCounter);
  316.       getmem(Win[WindowCounter],sizeof(Win[WindowCounter]^));    {allocate space}
  317.       if GoldMaxAvail > succ(Y2-Y1)*succ(X2-X1)*2 then
  318.       begin
  319.          VerifyWindowOnScreen(X1,Y1,X2,Y2);
  320.          OuterXY(X1,Y1,X2,Y2);
  321.          getmem(Win[WindowCounter]^.ScreenPtr,succ(Y2-Y1)*succ(X2-X1)*2);
  322.          PartSave(X1,Y1,X2,Y2,Win[WindowCounter]^.ScreenPtr^);
  323.          with Win[WindowCounter]^ do
  324.          begin
  325.            Coord.X1 := X1;
  326.            Coord.Y1 := Y1;
  327.            Coord.X2 := X2;
  328.            Coord.Y2 := Y2;
  329.            CursorFind(CursorX,CursorY,ScanTop,ScanBot);
  330.          end;  {with}
  331.       end;
  332.    end;
  333. end; {CreateWin}
  334.  
  335. procedure MkWin(x1,y1,x2,y2,FB,Boxtype:integer);
  336. {Main procedure for creating window}
  337. begin
  338.    if OnScreen then
  339.    begin
  340.       CreateWin(X1,Y1,X2,Y2);
  341.       FBox(x1,y1,x2,y2,FB,BoxType);
  342.       DrawShadow(X1,Y1,X2,Y2);
  343.    end;
  344. end; {MkWin}
  345.  
  346. procedure MkPopUpWin(var x1,y1,x2,y2:integer; FB1,FB2,style:byte);
  347. {Used by Pull down menus}
  348. begin
  349.    CreateWin(X1,Y1,X2,Y2);
  350.    VerifyWindowOnScreen(X1,Y1,X2,Y2);
  351.    case style of
  352.       1,2: begin
  353.          Box3D(x1,y1,x2,y2,FB1,FB2,1);
  354.          DrawShadow(X1,Y1,X2,Y2);
  355.       end;
  356.       3,4: begin
  357.          FBox(succ(x1),y1,pred(x2),y2,FB2,4);
  358.          DrawShadow(succ(X1),Y1,pred(X2),Y2);
  359.       end;
  360.    end;
  361.  
  362. end; {MkPopUpWin}
  363.  
  364. procedure GrowMKwin(x1,y1,x2,y2,FB,boxtype:integer);
  365. {same as MKwin but window explodes}
  366. var I : integer;
  367. begin
  368.    if OnScreen then
  369.    begin
  370.       CreateWin(X1,Y1,X2,Y2);
  371.       GrowFBox(x1,y1,x2,y2,FB,BoxType);
  372.       DrawShadow(X1,Y1,X2,Y2);
  373.       with Win[WindowCounter]^ do
  374.       begin
  375.          X1 := Coord.X1;
  376.          Y1 := Coord.Y1;
  377.          X2 := Coord.X2;
  378.          Y2 := Coord.Y2;
  379.       end;  {with}
  380.    end;
  381. end; {GrowMKwin}
  382.  
  383. procedure RmWin;
  384. begin
  385.     if OnScreen and (WindowCounter > 0) then
  386.     begin
  387.        with Win[WindowCounter]^ do
  388.        begin
  389.           with Coord do
  390.              PartRestore(X1,Y1,X2,Y2,ScreenPtr^);
  391.           CursorPos(CursorX,CursorY);
  392.           CursorSize(ScanTop,ScanBot);
  393.           with Coord do
  394.              freemem(ScreenPtr,succ(Y2-Y1)*succ(X2-X1)*2);
  395.           freemem(Win[WindowCounter],sizeof(Win[WindowCounter]^));
  396.        end; {with}
  397.        dec(WindowCounter);
  398.     end;
  399. end; {RmWin}
  400.  
  401.                          {***********************}
  402.                          {**  Window Routines  **}
  403.                          {***********************}
  404.  
  405. function LastWinInChain: WStructurePtr;
  406. {INTERNAL}
  407. var Temp: WStructurePtr;
  408. begin
  409.    Temp := WinVars.FirstWin;
  410.    while (Temp <> nil)
  411.      and (Temp^.NextWinPtr <> nil) do
  412.       Temp := Temp^.NextWinPtr;
  413.    LastWinInChain := Temp;
  414. end; {LastWinInChain}
  415.  
  416. function PrevWinInChain(WCP:WStructurePtr): WStructurePtr;
  417. {INTERNAL}
  418. var Temp: WStructurePtr;
  419. begin
  420.    Temp := WinVars.FirstWin;
  421.    if Temp = WCP then
  422.       Temp := nil
  423.    else
  424.    begin
  425.       while (Temp <> nil)
  426.         and (Temp^.NextWinPtr <> WCP) do
  427.          Temp := Temp^.NextWinPtr;
  428.    end;
  429.    PrevWinInChain := Temp;
  430. end; {PrevWinInChain}
  431.  
  432. function HighestWinNum:integer;
  433. {}
  434. var
  435.   Temp: WStructurePtr;
  436.   Num: integer;
  437. begin
  438.    Temp := WinVars.FirstWin;
  439.    if Temp <> nil then
  440.       Num := WinVars.FirstWin^.WinNum
  441.    else
  442.       Num := 0;
  443.    while (Temp <> nil) and (Temp^.NextWinPtr <> nil) do
  444.    begin
  445.       if Temp^.WinNum > Num then
  446.          Num := Temp^.WinNum;
  447.       Temp := Temp^.NextWinPtr;
  448.    end;
  449.    HighestWinNum := Num;
  450. end; {HighestWinNum}
  451.  
  452. function WinPtr(WinNum:integer):WStructurePtr;
  453. {Returns a pointer to the window structure}
  454. var Temp: WStructurePtr;
  455. begin
  456.    if WinNum = 0 then
  457.       WinPtr := LastWinInChain
  458.    else
  459.    begin
  460.       Temp := WinVars.FirstWin;
  461.       WinPtr := nil;
  462.       while (Temp <> nil) do
  463.       begin
  464.          if Temp^.WinNum = WinNum then
  465.          begin
  466.             WinPtr := Temp;
  467.             exit;
  468.          end
  469.          else
  470.             Temp := Temp^.NextWinPtr;
  471.       end;
  472.    end;
  473. end; {WinPtr}
  474.  
  475. function WinCount: integer;
  476. {}
  477. var
  478.   Temp: WStructurePtr;
  479.   Counter: integer;
  480. begin
  481.    Temp := WinVars.FirstWin;
  482.    Counter := 0;
  483.    while Temp <> nil do
  484.    begin
  485.       inc(Counter);
  486.       Temp := Temp^.NextWinPtr;
  487.    end;
  488.    WinCount := Counter;
  489. end; { WinCount }
  490.  
  491. procedure ActivateWindow(Win:word);
  492. {}
  493. var
  494.    Temp:WStructurePtr;
  495. begin
  496.    Temp := WinPtr(Win);
  497.    if Temp <> nil then
  498.       with Temp^ do
  499.       begin
  500.          VideoTarget.ScreenPtr := SurfacePtr;
  501.          VideoTarget.Width := Width;
  502.          VideoTarget.Depth := Depth;
  503.          VideoTarget.WX1 := WinX1;
  504.          VideoTarget.WY1 := WinY1;
  505.          VideoTarget.WX2 := WinX2;
  506.          VideoTarget.WY2 := WinY2;
  507.          VideoTarget.WindowActive := GetBitStatus(WinState,WinConfine);
  508.          VideoTarget.TargetType := WinTarget;
  509.          VideoTarget.TargetPtr := Temp;
  510.          VideoTarget.MoveCursor := Temp = LastWinInChain; {top window}
  511.      end;
  512. end; {ActivateWindow}
  513.  
  514. function WindowHasFocus: boolean;
  515. {}
  516. begin
  517.    WindowHasFocus := (VideoTarget.TargetType = WinTarget);
  518. end; { WindowHasFocus }
  519.  
  520. procedure ActivateTopWindow;
  521. {}
  522. var Temp: WStructurePtr;
  523. begin
  524.    Temp := LastWinInChain;
  525.    if Temp <> nil then
  526.       ActivateWindow(Temp^.WinNum);
  527. end; { ActivateTopWindow }
  528.  
  529. procedure WinSetRegion(WP:WStructurePtr);
  530. {}
  531. begin
  532.    with WP^ do
  533.    begin
  534.          case WinStyle of
  535.             0 : begin
  536.               WinX1 := 1;
  537.               WinY1 := 1;
  538.               WinX2 := width;
  539.               WinY2 := depth;
  540.             end;
  541.             5: begin
  542.               WinX1 := 2;
  543.               WinY1 := 4;
  544.               WinX2 := pred(width);
  545.               WinY2 := depth;
  546.             end;
  547.             7,8: begin
  548.               WinX1 := 3;
  549.               WinY1 := 2;
  550.               WinX2 := width - 2;
  551.               WinY2 := pred(depth);
  552.             end;
  553.             9: begin
  554.               WinX1 := 2;
  555.               WinY1 := 5;
  556.               WinX2 := pred(width);
  557.               WinY2 := pred(depth);
  558.             end;
  559.             else begin
  560.               WinX1 := 2;
  561.               WinY1 := 2;
  562.               WinX2 := pred(width);
  563.               WinY2 := pred(depth);
  564.             end;
  565.          end; {case}
  566.    end;
  567. end; { WinSetRegion }
  568.  
  569. function WinCreate(X1,Y1,X2,Y2:integer;Style:byte): integer; {returns window handle}
  570. {}
  571. var
  572.    T: TintElement;
  573.    MemNeeded: integer;
  574.    Temp: WStructurePtr;
  575.    Charsize: byte;
  576. begin
  577.    MemNeeded :=  sizeof(WinVars.FirstWin^)+
  578.                  succ(Y2-Y1)*succ(X2-X1)*2;
  579.    if GoldMaxAvail < MemNeeded then
  580.       WinCreate := 0
  581.    else
  582.    begin
  583.       if WinVars.FirstWin = nil then
  584.       begin
  585.          getmem(WinVars.FirstWin,sizeof(WinVars.FirstWin^));
  586.          WinList := WinVars.FirstWin;
  587.          Temp := WinVars.FirstWin;
  588.          SaveScreen(InternalScreen2);
  589.          BackBuffer := FastVars.Screen[InternalScreen2]^.ScreenPtr;
  590.          FrontUpdated := false;
  591.       end
  592.       else
  593.       begin
  594.         Temp := LastWinInChain;
  595.         getmem(Temp^.NextWinPtr,sizeof(WinVars.FirstWin^));
  596.         Temp := Temp^.NextWinPtr;
  597.       end;
  598.       with Temp^ do
  599.       begin
  600.          NextWinPtr := nil;
  601.          WinNum := 0;   {goofy but necessary!}
  602.          WinNum := succ(HighestWinNum);
  603.          WinStyle := Style;
  604.          Boundary := WinVars.Boundary;
  605.          for T := FirstWinCol to LastWinCol do
  606.              Col[T] := Tint[T];
  607.          WinState := WinVars.WinState;
  608.          Scroll := WinVars.Scroll;
  609.          MinWidth := WinVars.MinWidth;
  610.          MinDepth := WinVars.MinDepth;
  611.          fillchar(PreZoom,sizeof(PreZoom),#0);
  612.          StretchCallBack := NoStretchHook;
  613.          ProcessKeyProc := NoKeyHandler;   {used by Desktop}
  614.          CloseWinProc := BasicCloseHandler;
  615.          ChangeFocusProc := BasicFocusHandler;
  616.          WinCreate := WinNum;
  617.          Title := '';
  618.          Painted := false;
  619.          getmem(SurfacePtr,succ(Y2-Y1)*succ(X2-X1)*2);
  620.          X := X1;
  621.          Y := Y1;
  622.          Width := succ(X2-X1);
  623.          Depth := succ(Y2-Y1);
  624.          Cursor.X := 1;
  625.          Cursor.Y := 1;
  626.          CharSize := CharHeight;
  627.          Cursor.Top := CharSize-3;
  628.          Cursor.Bot := CharSize-2;
  629.          UserData := nil;
  630.       end;
  631.       WinSetRegion(Temp);
  632.    end;
  633. end; {WinCreate}
  634.  
  635. procedure WinSetPosition(Win:integer;NewX,NewY:shortint);
  636. {Changes the global position of the top left of the window; no
  637. error checking is performed so the window can be placed totally of the screen}
  638. var
  639.    Temp: WStructurePtr;
  640. begin
  641.    Temp := WinPtr(Win);
  642.    if Temp <> nil then
  643.    begin
  644.       Temp^.X := NewX;
  645.       Temp^.Y := NewY;
  646.    end;
  647. end; {WinSetPosition}
  648.  
  649. procedure WinSetMinSize(Win:integer;Width,Depth: byte);
  650. {}
  651. var
  652.    Temp: WStructurePtr;
  653. begin
  654.    Temp := WinPtr(Win);
  655.    if Temp <> nil then
  656.    begin
  657.       Temp^.MinWidth := Width;
  658.       Temp^.MinDepth := Depth;
  659.    end;
  660. end; { WinSetMinSize }
  661.  
  662. procedure WinSetType(Win:integer;W:WinType);
  663. {}
  664. var
  665.    Temp: WStructurePtr;
  666. begin
  667.    Temp := WinPtr(Win);
  668.    if Temp <> nil then
  669.    begin
  670.       with Temp^ do
  671.          case W of
  672.             WPlain: begin
  673.                Scroll := NoScroll;
  674.                SetBitStatus(WinState,WinAllowMove,false);
  675.                SetBitStatus(WinState,WinAllowClose,false);
  676.                SetBitStatus(WinState,WinAllowStretch,false);
  677.             end;
  678.             WClose: begin
  679.                Scroll := NoScroll;
  680.                SetBitStatus(WinState,WinAllowMove,false);
  681.                SetBitStatus(WinState,WinAllowClose,true);
  682.                SetBitStatus(WinState,WinAllowStretch,false);
  683.             end;
  684.             WMove: begin
  685.                Scroll := NoScroll;
  686.                SetBitStatus(WinState,WinAllowMove,true);
  687.                SetBitStatus(WinState,WinAllowClose,true);
  688.                SetBitStatus(WinState,WinAllowStretch,false);
  689.             end;
  690.             WMoveNoClose: begin
  691.                Scroll := NoScroll;
  692.                SetBitStatus(WinState,WinAllowMove,true);
  693.                SetBitStatus(WinState,WinAllowClose,false);
  694.                SetBitStatus(WinState,WinAllowStretch,false);
  695.             end;
  696.             WStretch: begin
  697.                Scroll := NoScroll;
  698.                SetBitStatus(WinState,WinAllowMove,true);
  699.                SetBitStatus(WinState,WinAllowClose,true);
  700.                SetBitStatus(WinState,WinAllowStretch,true);
  701.                SetBitStatus(WinState,WinSmartStretch,false);
  702.                StretchCallBack := NoStretchHook;
  703.             end;
  704.          end; {case}
  705.    end;
  706. end; {WinSetType}
  707.  
  708. procedure WinSetScrollType(Win:integer;S:ScrollType);
  709. {}
  710. var
  711.    Temp: WStructurePtr;
  712. begin
  713.    Temp := WinPtr(Win);
  714.    if Temp <> nil then
  715.       Temp^.Scroll := S;
  716. end; {WinSetScrollType}
  717.  
  718. procedure WinSetBoundary(Win,BX1,BY1,BX2,BY2:integer);
  719. {}
  720. var
  721.    Temp: WStructurePtr;
  722. begin
  723.    Temp := WinPtr(Win);
  724.    if Temp <> nil then
  725.       with Temp^.Boundary do
  726.       begin
  727.          X1 := BX1;
  728.          Y1 := BY1;
  729.          X2 := BX2;
  730.          Y2 := BY2;
  731.       end;
  732. end; {WinSetBoundary}
  733.  
  734. procedure WinSetColor(Win:integer; A:TintElement;C:byte);
  735. {}
  736. var
  737.    Temp: WStructurePtr;
  738. begin
  739.    Temp := WinPtr(Win);
  740.    if Temp <> nil then
  741.    begin
  742.       if A in [WinBorder..WinBorderOff] then
  743.          Temp^.Col[A] := C;
  744.    end;
  745. end; {WinSetColor}
  746.  
  747. procedure WinSetTitle(Win:integer;Tit:string);
  748. {}
  749. var
  750.    Temp: WStructurePtr;
  751. begin
  752.    Temp := WinPtr(Win);
  753.    if Temp <> nil then
  754.       Temp^.Title := Tit;
  755. end; {WinSetTitle}
  756.  
  757. procedure WinSetShowNum(Win:integer;On:boolean);
  758. {}
  759. var
  760.    Temp: WStructurePtr;
  761. begin
  762.    Temp := WinPtr(Win);
  763.    if Temp <> nil then
  764.       SetBitStatus(Temp^.WinState,WinShowNum,On);
  765. end; {WinSetShowNum}
  766.  
  767. procedure WinSetStretchProc(Win:integer;S:StretchProc);
  768. {}
  769. var
  770.    Temp: WStructurePtr;
  771. begin
  772.    Temp := WinPtr(Win);
  773.    if Temp <> nil then
  774.    begin
  775.       Temp^.StretchCallBack := S;
  776.       SetBitStatus(Temp^.WinState,WinSmartStretch,(@S <> @NoStretchHook));
  777.    end;
  778. end; {WinSetStretchProc}
  779.  
  780. procedure DrawHorizBar(WinId:integer;Current,Max: longint);
  781. {}
  782. var
  783.    Temp: WStructurePtr;
  784.   WasOn: boolean;
  785.   CursX,CursY : byte;
  786. begin
  787.    Temp := WinPtr(WinId);
  788.    if (Temp <> nil) and (Temp^.Scroll in [HorizScroll,BothScroll]) then
  789.    with Temp^ do
  790.    begin
  791.       CursX := WhereX;
  792.       CursY := WhereY;
  793.       WasOn := GetSetWinIgnore(true);
  794.          WriteHScrollBar(2,width-1,Depth,0,Current,Max);
  795.       if not WasOn then
  796.          SetWinIgnore(false);
  797.       GotoXY(CursX,CursY);
  798.    end;
  799. end; {DrawHorizBar}
  800.  
  801. procedure DrawVertBar(WinId:integer;Current,Max: longint);
  802. {}
  803. var
  804.    Temp: WStructurePtr;
  805.    WasOn: boolean;
  806.    CursX,CursY : byte;
  807. begin
  808.    Temp := WinPtr(WinId);
  809.    if (Temp <> nil) and (Temp^.Scroll in [VertScroll,BothScroll]) then
  810.    with Temp^ do
  811.    begin
  812.       CursX := WhereX;
  813.       CursY := WhereY;
  814.       WasOn := GetSetWinIgnore(true);
  815.       WriteVScrollBar(width,2,pred(depth),0,Current,Max);
  816.       if not WasOn then
  817.          SetWinIgnore(false);
  818.       GotoXY(CursX,CursY);
  819.    end;
  820. end; {DrawVertBar}
  821.  
  822. {     Window Styles:   0   -   No Border
  823.                        1   -   Single Line Border - Standard
  824.                        2   -   Double Line Border
  825.                        3   -   Title Bar (caption)
  826.                        4   -   Edge Border w/o title bar
  827.                        5   -   Menu Style a la Professional Write
  828.                        6   -   Edge Border with title bar
  829.                        7   -   Chisel Raised
  830.                        8   -   Chisel Sunken
  831. }
  832.  
  833. procedure WriteCustomCloseIcon(A:byte);
  834. {}
  835. begin
  836.    if FastVars.CustomCharsActive then
  837.       WriteAT(1,1,A,chr(206)+char(207))
  838.    else
  839.       WriteAT(1,1,A,' - ');
  840. end; { WriteCustomCloseIcon }
  841.  
  842. procedure WriteCustomZoomIcon(Width,A:byte);
  843. {}
  844. begin
  845.    if FastVars.CustomCharsActive then
  846.       WriteAT(pred(Width),1,A,chr(205)+char(216))
  847.    else
  848.       WriteAT(Width-2,1,A,'  ');
  849. end; { WriteCustomZoomIcon }
  850.  
  851. procedure DrawFrame(WinId:integer;Active:boolean);
  852. {}
  853. var
  854.    Temp: WStructurePtr;
  855.    YT:integer;
  856.    IgnoreState: boolean;
  857.    TheStyle: byte;
  858.    DrawNumbers: boolean;
  859.  
  860.    procedure DisplayTitle(A:byte);
  861.    {}
  862.    begin
  863.       with Temp^ do
  864.       begin
  865.          if Title <> '' then
  866.          begin
  867.             if (TheStyle = 5)
  868.             or (TheStyle = 9) then
  869.                YT := 2
  870.             else
  871.                YT:= 1;
  872.             if ((TheStyle in [1,2,7,8]) or ((TheStyle = 4) and (not FastVars.CustomCharsActive)))
  873.             and (length(Title) >= Width - 10 - 5*ord(DrawNumbers)) then
  874.                WriteCenter(YT,A,Squeeze('L',Title,Width - 10 - 5*ord(DrawNumbers)))
  875.             else if TheStyle in  [3,6] then
  876.                WriteCenter(YT,0,Title)
  877.             else
  878.                WriteCenter(YT,A,Title);
  879.          end;
  880.        end;
  881.    end; { DisplayTitle }
  882.  
  883.    procedure DisplayNumber(A:byte);
  884.    {}
  885.    begin
  886.       if DrawNumbers then with Temp^ do
  887.       begin
  888.          if ((TheStyle in [1,2,7,8]) or ((TheStyle = 4) and (not FastVars.CustomCharsActive)))
  889.          and GetBitStatus(WinState,WinAllowStretch)
  890.          and (Active or (WinVars.DesktopFadeStyle = 0))  then
  891.             WriteRight(Width-6,1,A,IntToStr(WinNum))
  892.          else if TheStyle in [4,6] then
  893.             WriteRight(Width-4,1,A,IntToStr(WinNum))
  894.          else
  895.             WriteRight(Width-2,1,A,IntToStr(WinNum));
  896.       end;
  897.    end; { DisplayNumber }
  898.  
  899.    procedure DisplayCloseIcon;
  900.    {}
  901.    begin
  902.       with Temp^ do
  903.       if GetBitStatus(WinState,WinAllowClose) then
  904.       begin
  905.          if (TheStyle in [1,2,7,8]) or ((TheStyle = 4) and (not FastVars.CustomCharsActive)) then
  906.          begin
  907.             case TheStyle of
  908.                7,8: begin
  909.                   WriteAT(3,1,Col[WinBorder3DIn],'<');
  910.                   WriteAT(5,1,Col[WinBorder3DOut],'>');
  911.                end
  912.                else
  913.                   WriteAT(3,1,Col[WinBorder],'[ ]');
  914.             end;
  915.             WriteAT(4,1,Col[WinIcons],WinVars.WinCloseChar);
  916.          end
  917.          else if TheStyle in [3,6] then
  918.              WriteCustomCloseIcon(Col[WinCustom]);
  919.       end;
  920.    end; { DisplayCloseIcon }
  921.  
  922.    procedure DisplayZoomIcon;
  923.    {}
  924.    begin
  925.       with Temp^ do
  926.       begin
  927.          if (TheStyle in [1,2,7,8]) or ((TheStyle = 4) and (not FastVars.CustomCharsActive)) then
  928.          begin
  929.             case TheStyle of
  930.                7,8: begin
  931.                   WriteAT(Width-4,1,Col[WinBorder3DIn],'<');
  932.                   WriteAT(Width-2,1,Col[WinBorder3DOut],'>');
  933.                end;
  934.                else
  935.                   WriteAT(Width-4,1,Col[WinBorder],'[ ]');
  936.             end; {case}
  937.             if not GetBitStatus(WinState,WinZoomed) then
  938.                WriteAT(Width-3,1,Col[WinIcons],WinVars.WinZoomMaxChar)
  939.             else
  940.                WriteAT(Width-3,1,Col[WinIcons],WinVars.WinZoomBackChar);
  941.          end
  942.          else if TheStyle in [3,6] then
  943.             WriteCustomZoomIcon(Width,Col[WinCustom]);
  944.       end; {case}
  945.    end; { DisplayZoomIcon }
  946.  
  947. begin
  948.    Temp := WinPtr(WinId);
  949.    if Temp <> nil then
  950.    with Temp^ do
  951.    begin
  952.       with WinVars do
  953.       begin
  954.          (*
  955.          if DesktopActive and (DesktopFocusStyle <> 0) then
  956.             TheStyle := DesktopFocusStyle
  957.          else
  958.             TheStyle := WinStyle;
  959.          *)
  960.          if DesktopActive and (DesktopFocusStyle <> 0) then
  961.             Temp^.WinStyle := DesktopFocusStyle;
  962.          TheStyle := WinStyle;
  963.          if not DesktopActive then
  964.             DrawNumbers := GetBitStatus(Temp^.WinState,WinShowNum)
  965.          else
  966.             case DesktopNums of
  967.                WShowNumbers: DrawNumbers := true;
  968.                WNoNumbers: DrawNumbers := false;
  969.                else DrawNumbers := GetBitStatus(Temp^.WinState,WinShowNum);
  970.             end; {case}
  971.       end;
  972.       ActivateWindow(WinId);
  973.       IgnoreState := GetSetWinIgnore(true);
  974.       if Active or (WinVars.DesktopFadeStyle = 0) then  {draw frame in all its glory}
  975.       begin
  976.          case TheStyle of
  977.             7:Box3D(1,1,width,depth,Col[WinBorder3dOut],Col[WinBorder3dIn],TheStyle);
  978.             8:Box3D(1,1,width,depth,Col[WinBorder3dIn],Col[WinBorder3dOut],TheStyle);
  979.             else
  980.                Box(1,1,width,depth,Col[WinBorder],TheStyle);
  981.          end; {case}
  982.          case TheStyle of
  983.             3,6: ClearText(1,1,Width,1,Col[WinCaption]);
  984.             7,8: ClearText(3,2,Width-2,depth-1,Col[WinBody]);
  985.          end; {case}
  986.          if TheStyle > 0 then
  987.             DisplayTitle(Col[WinTitle]);
  988.          DisplayCloseIcon;
  989.          {Write the stretch icon at lower right}
  990.          if ((TheStyle in [1,2,3,6,7,8]) or ((TheStyle = 4) and (not FastVars.CustomCharsActive)))
  991.             and GetBitStatus(WinState,WinAllowStretch) then
  992.          begin
  993.             case TheStyle of
  994.               1,4: WriteAt(Width,Depth,Col[WinIcons],'┘');
  995.               2: if FastVars.CustomCharsActive then
  996.                  WriteAt(Width,Depth,Col[WinIcons],'┘')
  997.               else
  998.                  WriteAt(Width,Depth,Col[WinIcons],'╝');
  999.               7,8: WriteAt(Width,Depth,Col[WinIcons],'»');
  1000.             end; {case}
  1001.             DisplayZoomIcon;
  1002.          end;
  1003.          if TheStyle in [3,6] then
  1004.             DisplayNumber(Col[WinCaption])
  1005.          else
  1006.             DisplayNumber(Col[WinBorder]);
  1007.          DrawVertBar(WinID,1,100);
  1008.          DrawHorizBar(WinID,1,100);
  1009.       end
  1010.       else   {draw inactive frame}
  1011.       begin
  1012.          Box(1,1,width,depth,Col[WinBorderOff],WinVars.DesktopFadeStyle);
  1013.          DisplayTitle(Col[WinBorderOff]);
  1014.          DisplayNumber(Col[WinBorderOff]);
  1015.       end;
  1016.       SetWinIgnore(IgnoreState);
  1017.    end; {with}
  1018. end; {DrawFrame}
  1019.  
  1020. procedure WinPaint(Win:integer);
  1021. {Draws the window border and scrolls, etc. based on the WinStyle setting}
  1022. var
  1023.    VW:videoword;
  1024.    Temp: WStructurePtr;
  1025. begin
  1026.    Temp := WinPtr(Win);
  1027.    if (Temp <> nil) then
  1028.       with Temp^ do
  1029.       begin
  1030.          VW.Ch := ' ';
  1031.          VW.Attr := Col[WinBody];
  1032.          FillVideo(SurfacePtr^,Width*Depth,VW);
  1033.          DrawFrame(Win,true);
  1034.          Painted := true;
  1035.       end;
  1036. end; { WinPaint }
  1037.  
  1038. procedure WinDisplay(Win:integer);
  1039. {}
  1040. var
  1041.    Temp: WStructurePtr;
  1042.    MemoryNeeded: longint;
  1043. begin
  1044.    Temp := WinPtr(Win);
  1045.    if Temp <> nil then
  1046.    begin
  1047.       WinVars.TopWin := Temp;
  1048.       if not Temp^.Painted then
  1049.          WinPaint(Win);
  1050.       with Temp^ do
  1051.          SetBitStatus(WinState,WinZoomed,
  1052.                          (X = Boundary.X1)
  1053.                           and (Y = Boundary.Y1)
  1054.                           and (X + pred(width) = Boundary.X2)
  1055.                           and (Y + pred(depth) = Boundary.Y2)
  1056.                       );
  1057.    end;
  1058. end; {WinDisplay}
  1059.  
  1060. procedure WinSetFrame(Win:integer;Bright:boolean);
  1061. {Changes the window frame}
  1062. var
  1063.    Temp: WStructurePtr;
  1064.    WI:boolean;
  1065. begin
  1066.    Temp := WinPtr(Win);
  1067.    if Temp <> nil then
  1068.    begin
  1069.       WI := GetSetWinIgnore(true);
  1070.       DrawFrame(Win,bright);
  1071.       if not WI then
  1072.          SetWinIgnore(false);
  1073.    end;
  1074. end; {WinSetFrame}
  1075.  
  1076. procedure WinDispose(Win:integer);
  1077. {Removes the Window from the Window list, and disposes of allocated win memory}
  1078. var
  1079.    Prev,TheWin: WStructurePtr;
  1080.    WasTarget: boolean;
  1081. begin
  1082.    TheWin := WinPtr(Win);
  1083.    if TheWin <> nil then
  1084.    begin
  1085.       WasTarget := (VideoTarget.TargetType = WinTarget)
  1086.                    and
  1087.                    (WStructurePtr(VideoTarget.TargetPtr)^.WinNum = Win);
  1088.       Prev := WinVars.FirstWin;
  1089.       if Prev = TheWin then {first window in list}
  1090.          WinVars.FirstWin := TheWin^.NextWinPtr
  1091.       else
  1092.       begin
  1093.          while (Prev <> nil) and (Prev^.NextWinPtr <> TheWin) do
  1094.             Prev := Prev^.NextWinPtr;
  1095.          if Prev <> nil then
  1096.             Prev^.NextWinPtr := Prev^.NextWinPtr^.NextWinPtr; {pull window out of list}
  1097.       end;
  1098.       {free the memory allocated in TheWin}
  1099.       with TheWin^ do
  1100.          freemem(SurfacePtr,Width*Depth*2);
  1101.       freemem(TheWin,sizeof(TheWin^));
  1102.       if WinVars.FirstWin = nil then {last window removed dispose of screens}
  1103.       begin
  1104.          RestoreScreen(InternalScreen2);
  1105.          DisposeScreen(InternalScreen2);
  1106.          BackBuffer := nil;
  1107.          if WasTarget then
  1108.             ActivateVisibleScreen;
  1109.          WinList := nil;
  1110.          WinVars.TopWin := nil;
  1111.       end
  1112.       else
  1113.       begin
  1114.          WinVars.TopWin := lastWinInChain;
  1115.          if WasTarget then
  1116.             ActivateWindow(WinVars.TopWin^.WinNum);
  1117.          WinDrawAll;
  1118.          {restore cursor for new top window}
  1119.          with WinVars.TopWin^.Cursor do
  1120.          begin
  1121.             GotoXY(X,Y);
  1122.             CursorSize(Top,Bot);
  1123.          end;
  1124.       end;
  1125.    end;
  1126. end; {WinDispose}
  1127.  
  1128.                          {***********************}
  1129.                          {**  Moving Routines  **}
  1130.                          {***********************}
  1131.  
  1132. procedure MoveWin(UsingMouse:boolean;OldX,OldY:integer);
  1133. {Drags window around screen}
  1134. var
  1135.   Handle:integer;
  1136.   DeltaX, DeltaY,
  1137.   W,X1,Y1: integer;
  1138.   MX,MY: byte;
  1139.   Mvisible,
  1140.   WasOn,
  1141.   Left,Center,Right : boolean;
  1142.   ActiveWinPtr: WStructurePtr;
  1143.   T,B,CX,CY: byte;                   {cursor size}
  1144. begin
  1145.    ActiveWinPtr := LastWinInChain;
  1146.    if not UsingMouse then  {display Instructions on screen}
  1147.    begin
  1148.       W := length(WinVars.WinMoveMsgPart1)+2;
  1149.       X1 := (80 - W) div 2;
  1150.       Y1 := (HardVars.Depth - 3) div 2;
  1151.       Handle := WinCreate(X1,Y1,succ(X1+W),Y1+3,4);
  1152.       WinSetColor(Handle,WinBorder,Tint[WinMoveBody]);
  1153.       WinSetColor(Handle,WinIcons,Tint[WinMoveBody]);
  1154.       WinSetColor(Handle,WinBody,Tint[WinMoveBody]);
  1155.       WinPaint(Handle);
  1156.       ActivateWindow(handle);
  1157.       WriteCenter(1,0,WinVars.WinMoveMsgPart1);
  1158.       X1 := length(WinVars.WinMoveMsgPart2) - CharCount(HiMarker,WinVars.WinMoveMsgPart2);
  1159.       X1 := succ((W-X1) div 2);
  1160.       if X1 < 1 then
  1161.          X1 := 1;
  1162.       WriteHi(X1,2,Tint[WinMoveHi],Tint[WinMoveBody],WinVars.WinMoveMsgPart2);
  1163.       WinDrawAll;
  1164.       with WinVars.TopWin^.Cursor do
  1165.           GotoXY(W div 2,2);
  1166.    end
  1167.    else
  1168.    begin
  1169.       Handle := 0;
  1170.       MouseConfine(1,1+BBTop,80,HardVars.Depth - BBBot);
  1171.    end;
  1172.    CursorFind(CX,CY,T,B);
  1173.    repeat
  1174.      if UsingMouse then
  1175.      begin
  1176.         MouseShow(true);
  1177.         MouseStatus(Left,Center,Right,MX,MY);
  1178.      end
  1179.      else
  1180.      begin
  1181.         OldX := 20;
  1182.         OldY := 20;
  1183.         MY := 20;
  1184.         MX := 20;
  1185.         GetInput;
  1186.         case KeyVars.LastKey of
  1187.            328: dec(MY); {up}
  1188.            336: inc(MY); {down}
  1189.            333: inc(MX); {right}
  1190.            331: dec(MX); {left}
  1191.         end; {case}
  1192.         Left := true;
  1193.      end;
  1194.      DeltaX := MX - OldX;
  1195.      DeltaY := MY - OldY;
  1196.      {see if window would be partially visible}
  1197.      with ActiveWinPtr^ do
  1198.      begin
  1199.         if  ( (pred(X + Width) + DeltaX >= Boundary.X1)
  1200.               and (X + DeltaX <= Boundary.X2)
  1201.             )
  1202.         and ( (pred(Y + Depth) + DeltaY >= Boundary.Y1)
  1203.               and (Y + DeltaY <= Boundary.Y2)
  1204.             )  then
  1205.         begin
  1206.            inc(X, DeltaX);
  1207.            inc(Y, DeltaY);
  1208.         end;
  1209.         if (DeltaX <> 0) or (DeltaY <> 0) then
  1210.         begin
  1211.            WinDrawAll;
  1212.            if UsingMouse then with ActiveWinPtr^.Cursor do
  1213.            begin
  1214.               CursorSize(T,B);
  1215.               GotoXY(X,Y);
  1216.            end;
  1217.         end;
  1218.      end;
  1219.      OldX := MX;
  1220.      OldY := MY;
  1221.   until (UsingMouse and (Left = false))
  1222.      or (((KeyVars.LastKey = 13)
  1223.           or
  1224.           (KeyVars.LastKey = 27)) and (UsingMouse = false)
  1225.         );
  1226.   if Handle <> 0 then
  1227.      WinDispose(Handle)
  1228.   else
  1229.      MouseConfine(1,1,80,HardVars.Depth);
  1230. end; {MoveWin}
  1231.  
  1232.                        {***************************}
  1233.                        {**  Stretching Routines  **}
  1234.                        {***************************}
  1235.  
  1236. procedure WinToggleZoom;
  1237. {zooms or unzooms a window}
  1238. var WasZoomed: boolean;
  1239. begin
  1240.    with WinVars.TopWin^ do
  1241.    begin
  1242.       WasZoomed := GetBitStatus(WinState,WinZoomed);
  1243.       if not WasZoomed and
  1244.          (GoldMemAvail < (succ(Boundary.X2 - Boundary.X1)
  1245.                         * succ(Boundary.Y2 - Boundary.Y1)
  1246.                         * 2)
  1247.                         -
  1248.                         (Width*Depth*2)
  1249.          ) then
  1250.          exit; {no memory for new larger window}
  1251.       SetBitStatus(WinState,WinZoomed,not WasZoomed);
  1252.       freemem(SurfacePtr,Width*Depth*2);
  1253.       if WasZoomed then
  1254.       begin
  1255.          if PreZoom.X1 <> 0 then
  1256.          begin
  1257.             X :=  PreZoom.X1;   {set zone coords back to the old coords}
  1258.             Y :=  PreZoom.Y1;
  1259.             Width := succ(PreZoom.X2 - PreZoom.X1);
  1260.             Depth := succ(PreZoom.Y2 - PreZoom.Y1);
  1261.          end;
  1262.       end
  1263.       else
  1264.       begin
  1265.          PreZoom.X1 := X;  {save the un-zoomed coordinates}
  1266.          PreZoom.Y1 := Y;
  1267.          PreZoom.X2 := pred(X + Width);
  1268.          PreZoom.Y2 := pred(Y + Depth);
  1269.          X := Boundary.X1; {set window coords to the maximum}
  1270.          Y := Boundary.Y1 + BBTop;
  1271.          Width := succ(Boundary.X2 - Boundary.X1);
  1272.          Depth := succ(Boundary.Y2 - Boundary.Y1) - BBBot - BBTop;
  1273.       end;
  1274.       getmem(SurfacePtr,width*depth*2);
  1275.       WinSetRegion(WinVars.TopWin);
  1276.       ActivateWindow(0);   {update video target}
  1277.       WinPaint(0);
  1278.    end;
  1279. end; {WinToggleZoom}
  1280.  
  1281. procedure WinPostStretch(X1,Y1,X2,Y2: integer);
  1282. {}
  1283. var Zoomed: boolean;
  1284. begin
  1285.    ActivateTopWindow;
  1286.    with WinVars.TopWin^ do
  1287.    begin
  1288.       Zoomed := (X1 = Boundary.X1)
  1289.                 and (Y1 = Boundary.Y1)
  1290.                 and (X2 = Boundary.X2)
  1291.                 and (Y2 = Boundary.Y2);
  1292.       SetBitStatus(WinState,WinZoomed,Zoomed);
  1293.       if Zoomed then
  1294.       begin
  1295.          PreZoom.X1 := X;  {save the un-zoomed coordinates}
  1296.          PreZoom.Y1 := Y;
  1297.          PreZoom.X2 := pred(X + Width);
  1298.          PreZoom.Y2 := pred(Y + Depth);
  1299.       end;
  1300.       X := X1;
  1301.       Y := Y1;
  1302.       Width := succ(X2-X1);
  1303.       Depth := succ(Y2-Y1);
  1304.       getmem(SurfacePtr,width*depth*2);
  1305.    end;
  1306.    WinSetRegion(WinVars.TopWin);
  1307.    ActivateWindow(0);   {update video target}
  1308.    WinPaint(0);
  1309. end; { WinPostStretch }
  1310.  
  1311. procedure WinStretch(UsingMouse:boolean;OldX,OldY:byte);
  1312. {}
  1313. const
  1314.    BorderChar = '█';
  1315.    BorderCol = white;
  1316. var
  1317.    Mvisible,
  1318.    IgnoreState,
  1319.    Zoomed,
  1320.    Left,Center,Right : boolean;
  1321.    MX,MY: byte;
  1322.    CTop,CBot,CX,CY:byte;
  1323.    NewX,NewY: byte;
  1324.    X1,Y1,X2,Y2: byte;
  1325.  
  1326.    procedure DisplayStrip(X1,Y1,X2,Y2:byte);
  1327.    {}
  1328.    begin
  1329.       MoveToScreen(X1,Y1,X2,Y2,HardVars.Width,FrontBuffer^,X1,Y1,HardVars.Width,HardVars.ScreenPtr^);
  1330.    end; { DisplayStrip }
  1331.  
  1332.    procedure ChangePerimeter;
  1333.    {}
  1334.    var
  1335.      I : integer;
  1336.    begin
  1337.       if MVisible then
  1338.          MouseShow(false);
  1339.       with WinVars.TopWin^ do
  1340.       begin
  1341.          if NewX <> X2 then
  1342.          begin
  1343.             DisplayStrip(X2,Y1,X2,Y2);
  1344.             if NewX < X2 then
  1345.             begin
  1346.                DisplayStrip(succ(NewX),Y1,X2,Y2);
  1347.                DisplayStrip(succ(NewX),Y2,X2,Y2);
  1348.             end;
  1349.          end; {with}
  1350.          if NewY <> Y2 then
  1351.          begin
  1352.             DisplayStrip(X1,Y2,X2,Y2);
  1353.             if NewY < Y2 then
  1354.             begin
  1355.                DisplayStrip(X1,succ(NewY),X2,Y2);
  1356.                DisplayStrip(X2,succ(NewY),X2,Y2);
  1357.             end;
  1358.          end; {with}
  1359.          {draw new perimiter}
  1360.          X2 := NewX;
  1361.          Y2 := NewY;
  1362.          Box(X1,Y1,X2,Y2,Cattr(white,black),ord(BorderChar));
  1363.       end; {with}
  1364.       if MVisible then
  1365.          MouseShow(true);
  1366.    end; {ChangePerimeter}
  1367.  
  1368. begin
  1369.    if GoldMaxAvail < 2*HardVars.Width*HardVars.Depth then
  1370.    begin
  1371.       Beep;
  1372.       exit;
  1373.    end;
  1374.    MVisible := KeyVars.MouseVisible;
  1375.    IgnoreState := GetSetWinIgnore(true);
  1376.    WinRedraw(false);    {creates image of display at FrontBuffer}
  1377.    with WinVars.TopWin^ do
  1378.       freemem(SurfacePtr,Width*Depth*2);
  1379.    X1 := WinVars.TopWin^.X;
  1380.    Y1 := WinVars.TopWin^.Y;
  1381.    X2 := X1 + pred(WinVars.TopWin^.Width);
  1382.    Y2 := Y1 + pred(WinVars.TopWin^.Depth);
  1383.    ActivateVisibleScreen;
  1384.    Box(X1,Y1,X2,Y2,Cattr(Bordercol,black),ord(BorderChar));
  1385.    OldX := X2;
  1386.    OldY := Y2;
  1387.    CursorFind(CX,CY,CTop,CBot);
  1388.    CursorOff;
  1389.    repeat
  1390.       if UsingMouse then
  1391.       begin
  1392.          MouseShow(true);
  1393.          MouseStatus(Left,Center,Right,MX,MY);
  1394.       end
  1395.       else
  1396.       begin
  1397.          OldX := X2;
  1398.          OldY := Y2;
  1399.          MY := OldY;
  1400.          MX := OldX;
  1401.          GetInput;
  1402.          case KeyVars.LastKey of
  1403.             328: dec(MY); {up}
  1404.             336: inc(MY); {down}
  1405.             333: inc(MX); {right}
  1406.             331: dec(MX); {left}
  1407.          end; {case}
  1408.          Left := true;
  1409.       end;
  1410.       if Left and ( (MX <> OldX) or (MY <> OldY) ) then  {stretch window}
  1411.       begin
  1412.          if (succ(MX - X1 ) < WinVars.TopWin^.MinWidth) then  {too small}
  1413.             NewX := pred(X1 + WinVars.TopWin^.MinWidth)
  1414.          else
  1415.          if (MX > WinVars.TopWin^.Boundary.X2) then                 {out of bounds}
  1416.             NewX := WinVars.TopWin^.Boundary.X2
  1417.          else
  1418.             NewX := MX;
  1419.          if (succ(MY - Y1 ) < WinVars.TopWin^.MinDepth) then  {too small}
  1420.             NewY := pred(Y1 + WinVars.TopWin^.MinDepth)
  1421.          else
  1422.          if (MY > WinVars.TopWin^.Boundary.Y2) then                 {out of bounds}
  1423.             NewY := WinVars.TopWin^.Boundary.Y2
  1424.          else
  1425.             NewY := MY;
  1426.          ChangePerimeter;
  1427.          WinVars.TopWin^.StretchCallBack(X1,Y1,X2,Y2);
  1428.          OldX := NewX;
  1429.          OldY := NewY;
  1430.       end; {if}
  1431.    until (UsingMouse and (Left = false)) or (((KeyVars.LastKey =13) or (KeyVars.LastKey = 27)) and (UsingMouse = false));
  1432.    WinPostStretch(X1,Y1,X2,Y2);
  1433.    SetWinIgnore(IgnoreState);
  1434.    GotoXY(1,1);
  1435.    CursorSize(CTop,CBot);
  1436.    if MVisible then
  1437.       MouseShow(true);
  1438. end; {WinStretch}
  1439.  
  1440.                      {*******************************}
  1441.                      {**  Changing Focus Routines  **}
  1442.                      {*******************************}
  1443. procedure WinFadeTopWin;
  1444. {Turns the border of the top window to the "not-focussed" state}
  1445. var
  1446.    Temp: WStructurePtr;
  1447. begin
  1448.    Temp := WinPtr(0);
  1449.    if (Temp <> nil) then
  1450.       DrawFrame(Temp^.WinNum,false);
  1451. end; {WinFadeTopWin}
  1452.  
  1453. procedure WinFocusTopWin;
  1454. {Turns the border of the top window to the "focussed" state}
  1455. var
  1456.    Temp: WStructurePtr;
  1457. begin
  1458.    Temp := WinPtr(0);
  1459.    if (Temp <> nil) then
  1460.       DrawFrame(Temp^.WinNum,true);
  1461. end; {WinFadeFocusWin}
  1462.  
  1463. procedure WinChangeFocus(WinId:integer);
  1464. {Brings the window to the top of the visible stack, i.e. to the
  1465.  bottom of the list}
  1466. var
  1467.    TheWin,TempWin: WStructurePtr;
  1468. begin
  1469.    TheWin := WinPtr(WinId);
  1470.    if (TheWin <> nil) and (TheWin <> LastWinInChain) then
  1471.    begin
  1472.       WinFadeTopWin;
  1473.       if TheWin = WinVars.FirstWin then
  1474.       begin
  1475.          WinVars.FirstWin := WinVars.FirstWin^.NextWinPtr;
  1476.          WinList := WinVars.FirstWin;
  1477.       end
  1478.       else
  1479.       begin
  1480.          TempWin := PrevWinInChain(TheWin);
  1481.          TempWin^.NextWinPtr := TempWin^.NextWinPtr^.NextWinPtr;
  1482.       end;
  1483.       TempWin := LastWinInChain;
  1484.       TempWin^.NextWinPtr := TheWin;
  1485.       TheWin^.NextWinPtr := nil;
  1486.       WinVars.TopWin := TheWin;
  1487.       WinFocusTopWin;
  1488.       WinDrawAll;
  1489.       {move the cursor?}
  1490.    end;
  1491. end; {WinChangeFocus}
  1492.  
  1493. procedure DeskNextWinCoords(var TLX,TLY: byte);
  1494. {Returns the position of the top left of the next new window on the desktop}
  1495. var
  1496.    X1,Y1: integer;
  1497.    Temp: WStructurePtr;
  1498.  
  1499.    procedure SetTopLeft;
  1500.    {}
  1501.    begin
  1502.       Y1 := succ(BBTop);
  1503.       X1 := 1;
  1504.    end; { SetTopLeft }
  1505.  
  1506. begin
  1507.    Temp := WinPtr(0);
  1508.    if Temp <> nil then with temp^ do
  1509.    begin
  1510.       X1 := succ(X);
  1511.       Y1 := succ(Y);
  1512.       if (X1 < 1) or (X1 > HardVars.Width - 3)
  1513.       or (Y1 < succ(BBTop)) or (Y1 > HardVars.depth-BBbot - 2) then
  1514.          SetTopLeft;
  1515.    end
  1516.    else
  1517.       SetTopLeft;
  1518.    TLX := X1;
  1519.    TLY := Y1;
  1520. end; { DeskNextWinCoords }
  1521.  
  1522. function WinWithFocus:integer;
  1523. {Returns the ID of the window at the top}
  1524. begin
  1525.    if WinVars.TopWin = nil then
  1526.       WinWithFocus := 0
  1527.    else
  1528.       WinWithFocus := WinVars.TopWin^.WinNum;
  1529. end; { WinWithFocus }
  1530.  
  1531. procedure WinShiftFocus;
  1532. {Rotates the window list so the top window moves to the bottom}
  1533. begin
  1534.  
  1535. end; { WinShiftFocus }
  1536.  
  1537. function CloseTrace(CX,CY:byte): boolean;
  1538. {Follows cursor around to see if user releases button over close icon}
  1539. var
  1540.    L,M,R,Ignore,Down: boolean;
  1541.    X,Y: byte;
  1542. begin
  1543.    Ignore := GetSetWinIgnore(true);
  1544.    Down := false;
  1545.    repeat
  1546.       MouseStatus(L,M,R,X,Y);
  1547.       if (Y = CY) and (X >= CX) and (X <= CX+2) then
  1548.       begin
  1549.          if not down then
  1550.          begin
  1551.             WritePlain(4,1,WinVars.WinCloseCharDown);
  1552.             WinDrawTop;
  1553.             Down:= true;
  1554.          end;
  1555.       end
  1556.       else
  1557.       begin
  1558.          if Down then
  1559.          begin
  1560.             WritePlain(4,1,WinVars.WinCloseChar);
  1561.             WinDrawTop;
  1562.             Down := false;
  1563.          end;
  1564.       end;
  1565.    until not L;
  1566.    WritePlain(4,1,WinVars.WinCloseChar);
  1567.    SetWinIgnore(Ignore);
  1568.    CloseTrace := (Y = CY) and (X >= CX) and (X <= CX+2);
  1569. end; { CloseTrace }
  1570.  
  1571. function CloseTraceCustom(CX,CY:byte): boolean;
  1572. {Follows cursor around to see if user releases button over close icon}
  1573. var
  1574.    L,M,R,Ignore,Down: boolean;
  1575.    X,Y,A1,A2: byte;
  1576. begin
  1577.    A1 := WinPtr(0)^.Col[WinCustom];
  1578.    A2 := WinPtr(0)^.Col[WinIcons];
  1579.    if A2 = A1 then
  1580.       A2 := 95;
  1581.    Down := false;
  1582.    Ignore := GetSetWinIgnore(true);
  1583.    repeat
  1584.       MouseStatus(L,M,R,X,Y);
  1585.       if (Y = CY) and (X >= CX) and (X <= succ(CX)+ ord(not FastVars.CustomCharsActive)) then
  1586.       begin
  1587.          if not down then
  1588.          begin
  1589.             WriteCustomCloseIcon(A2);
  1590.             MouseShow(false);
  1591.             WinDrawTop;
  1592.             Down:= true;
  1593.          end;
  1594.       end
  1595.       else
  1596.       begin
  1597.          if Down then
  1598.          begin
  1599.             WriteCustomCloseIcon(A1);
  1600.             WinDrawTop;
  1601.             MouseShow(true);
  1602.             Down := false;
  1603.          end;
  1604.       end;
  1605.    until not L;
  1606.    SetWinIgnore(Ignore);
  1607.    MouseShow(true);
  1608.    CloseTraceCustom := (Y = CY) and (X >= CX) and (X <= succ(CX)+ ord(not FastVars.CustomCharsActive));
  1609. end; { CloseTraceCustom }
  1610.  
  1611. function ZoomTrace(CX,CY:byte): boolean;
  1612. {Follows cursor around to see if user releases button over zoom icon}
  1613. var
  1614.    L,M,R,Ignore,Down: boolean;
  1615.    TempX,TempY: byte;
  1616.    WP: WStructurePtr;
  1617. begin
  1618.    Ignore := GetSetWinIgnore(true);
  1619.    Down := false;
  1620.    WP := WinPtr(0);
  1621.    with WP^ do
  1622.    repeat
  1623.       MouseStatus(L,M,R,TempX,TempY);
  1624.       if (TempY = CY) and (TempX >= CX) and (TempX <= CX+2) then
  1625.       begin
  1626.          if not down then
  1627.          begin
  1628.             WritePlain(Width-3,1,WinVars.WinCloseCharDown);
  1629.             WinDrawTop;
  1630.             Down:= true;
  1631.          end;
  1632.       end
  1633.       else
  1634.       begin
  1635.          if Down then
  1636.          begin
  1637.             if GetBitStatus(WinState,WinZoomed) then
  1638.                WritePlain(width-3,1,WinVars.WinZoomBackChar)
  1639.             else
  1640.                WritePlain(width-3,1,WinVars.WinZoomMaxChar);
  1641.             WinDrawTop;
  1642.             Down := false;
  1643.          end;
  1644.       end;
  1645.    until not L;
  1646.    SetWinIgnore(Ignore);
  1647.    with WP^ do
  1648.       ZoomTrace := (TempY = CY) and (TempX >= CX) and (TempX <= CX+2);
  1649. end; { ZoomTrace }
  1650.  
  1651. function ZoomTraceCustom(CX,CY:byte): boolean;
  1652. {Follows cursor around to see if user releases button over zoom icon}
  1653. var
  1654.    L,M,R,Ignore,Down: boolean;
  1655.    WX,TempX,TempY,A1,A2: byte;
  1656.    WP: WStructurePtr;
  1657. begin
  1658.    WP := WinPtr(0);
  1659.    A1 := WP^.Col[WinCustom];
  1660.    A2 := WP^.Col[WinIcons];
  1661.    WX := WP^.Width;
  1662.    if A2 = A1 then
  1663.       A2 := 95;
  1664.    Down := false;
  1665.    Ignore := GetSetWinIgnore(true);
  1666.    with WP^ do
  1667.    repeat
  1668.       MouseStatus(L,M,R,TempX,TempY);
  1669.       if (TempY = CY) and (TempX >= CX-1-ord(not FastVars.CustomCharsActive)) and (TempX <= CX) then
  1670.       begin
  1671.          if not down then
  1672.          begin
  1673.             WriteCustomZoomIcon(WX,A2);
  1674.             MouseShow(false);
  1675.             WinDrawTop;
  1676.             Down:= true;
  1677.          end;
  1678.       end
  1679.       else
  1680.       begin
  1681.          if Down then
  1682.          begin
  1683.             WriteCustomZoomIcon(WX,A1);
  1684.             WinDrawTop;
  1685.             MouseShow(true);
  1686.             Down := false;
  1687.          end;
  1688.       end;
  1689.    until not L;
  1690.    SetWinIgnore(Ignore);
  1691.    MouseShow(true);
  1692.    with WP^ do
  1693.       ZoomTraceCustom := (TempY = CY) and (TempX >= CX-1-ord(not FastVars.CustomCharsActive)) and (TempX <= CX);
  1694. end; { ZoomTraceCustom }
  1695.  
  1696.                      {*******************************}
  1697.                      {**  Key Management Routines  **}
  1698.                      {*******************************}
  1699.  
  1700. function IsWinKey(K:word;KX,KY:Integer):boolean;
  1701. {}
  1702. begin
  1703.    with WinVars do
  1704.      IsWinKey := (((K = Movekey) or (K =DeskCascadeKey)) and GetBitStatus(TopWin^.WinState,WinAllowMove))
  1705.                  or
  1706.                  (((K = ZoomKey) or (K=StretchKey) or (K=DeskTileKey)) and GetBitStatus(TopWin^.WinState,WinAllowStretch))
  1707.                  or
  1708.                  ((K = CloseKey) and GetBitStatus(TopWin^.WinState,WinAllowClose))
  1709.                  or
  1710.                  ( ((K = 500) or (K = 520) or (K=540))
  1711.                    and
  1712.                    OnBorder(KX,KY,TopWin^.X,TopWin^.Y,TopWin^.Width,TopWin^.Depth)
  1713.                  );
  1714. end; {IsWinKey}
  1715.  
  1716. function IsFocusKey(K:word;KX,KY:Integer):byte;
  1717. {Returns the ID of the window that is to assume focus, or
  1718.  zero if there is no focus change}
  1719. var Temp: WStructurePtr;
  1720. begin
  1721.    IsFocusKey := 0;
  1722.    if (K >= 376) and (K <= 385) then {Alt-1 to Alt-0}
  1723.    begin
  1724.       Temp := WinPtr(K - 375);
  1725.       if Temp <> nil then
  1726.       begin
  1727.          IsFocusKey := K - 375;
  1728.          exit;
  1729.       end;
  1730.    end;
  1731.    if K = 500 then
  1732.    begin
  1733.       Temp := LastWinInChain;
  1734.       if not WithinBorder(KX,KY,Temp^.X,Temp^.Y,Temp^.Width,Temp^.Depth) then
  1735.          while Temp <> nil do
  1736.          begin
  1737.             Temp := PrevWinInChain(Temp);
  1738.             if WithinBorder(KX,KY,Temp^.X,Temp^.Y,Temp^.Width,Temp^.Depth) then
  1739.             begin
  1740.                IsFocusKey := Temp^.WinNum;
  1741.                exit;
  1742.             end;
  1743.          end;
  1744.    end;
  1745. end; {IsFocusKey}
  1746.  
  1747. procedure WinProcessKey(var K:word; var KX,KY:byte);
  1748. {}
  1749. var PosX,PosY: shortint;
  1750. begin
  1751.    if WinVars.TopWin <> nil then
  1752.       with WinVars.TopWin^ do
  1753.       begin
  1754.          if (K = DeskCascadeKey) and GetBitStatus(WinState,WinAllowMove) then
  1755.          begin
  1756.             X := KeyVars.LastX;
  1757.             Y := KeyVars.LastY;
  1758.             if GetBitStatus(WinState,WinAllowStretch)  then {stretch to lower right of desktop}
  1759.             begin
  1760.                K := 602;
  1761.                Width := HardVars.Width - pred(X);
  1762.                Depth := HardVars.Depth - pred(Y) - BBBot;
  1763.             end
  1764.             else {just move the top left position of the window}
  1765.                K := 601;
  1766.          end
  1767.          else if (K = DeskTileKey) and GetBitStatus(WinState,WinAllowMove)
  1768.               and GetBitStatus(WinState,WinAllowStretch) then
  1769.          begin
  1770.             K := 602;
  1771.             X := KeyVars.LastX;
  1772.             Y := KeyVars.LastY;
  1773.          end
  1774.          else if (K = WinVars.StretchKey) and GetBitStatus(WinState,WinAllowStretch) then
  1775.          begin
  1776.             WinStretch(false,X,Y);
  1777.             K := 602;
  1778.          end
  1779.          else if (K = WinVars.ZoomKey) and GetBitStatus(WinState,WinAllowStretch) then
  1780.          begin
  1781.             WinToggleZoom;
  1782.             K := 602;
  1783.          end
  1784.          else if (K = WinVars.CloseKey) and GetBitStatus(WinState,WinAllowClose) then
  1785.          begin
  1786.             K := 600;
  1787.          end
  1788.          else if (K = WinVars.MoveKey) and GetBitStatus(WinState,WinAllowMove) then
  1789.          begin
  1790.             PosX := X;
  1791.             PosY := Y;
  1792.             MoveWin(false,X,Y);
  1793.             if (PosX <> X) or (PosY <> Y) then
  1794.                K := 601;
  1795.          end
  1796.          else if (K = 500) then
  1797.          begin
  1798.             if (KX = X + pred(Width)) and (KY = Y + pred(Depth)) and GetBitStatus(WinState,WinAllowStretch) then
  1799.             begin
  1800.                WinStretch(true,KX,KY);
  1801.                K := 602;
  1802.             end else if (KY = Y) and (KX >= X) and (KX < X+width) then
  1803.             begin
  1804.                if (KX >= X + 2)
  1805.                and (KX <= X + 4)
  1806.                and GetBitStatus(WinState,WinAllowClose)
  1807.                and ( (WinStyle in [1,2,7,8]) or ((WinStyle = 4) and (not FastVars.CustomCharsActive))) then
  1808.                begin
  1809.                   if CloseTrace(X + 2,Y) then
  1810.                      K := 600;  {Closed}
  1811.                end
  1812.                else if (KX >= X)
  1813.                and (KX <= succ(X) + ord(not FastVars.CustomCharsActive))
  1814.                and GetBitStatus(WinState,WinAllowClose)
  1815.                and (WinStyle in [3,6]) then
  1816.                begin
  1817.                   if CloseTraceCustom(X,Y) then
  1818.                      K := 600;
  1819.                end
  1820.                else if (KX >= X + width - 5)
  1821.                and (KX <= X + width - 3)
  1822.                and GetBitStatus(WinState,WinAllowStretch)
  1823.                and ( (WinStyle in [1,2,7,8]) or ((WinStyle = 4) and (not FastVars.CustomCharsActive))) then
  1824.                begin
  1825.                   if ZoomTrace(X + width - 5,Y) then
  1826.                   begin
  1827.                      WinToggleZoom;
  1828.                      K := 602;
  1829.                   end;
  1830.                end
  1831.                else if (KX >= X + width - 2 - ord(not FastVars.CustomCharsActive))
  1832.                and (KX <= X + pred(width))
  1833.                and GetBitStatus(WinState,WinAllowStretch)
  1834.                and (WinStyle in [3,6]) then
  1835.                begin
  1836.                   if ZoomTraceCustom(X + pred(width),Y) then
  1837.                   begin
  1838.                      WinToggleZoom;
  1839.                      K := 602;
  1840.                   end;
  1841.                end
  1842.                else if GetBitStatus(WinState,WinAllowMove) then
  1843.                begin
  1844.                   PosX := X;
  1845.                   PosY := Y;
  1846.                   MoveWin(true,KX,KY);
  1847.  
  1848.                   if (PosX <> X) and (PosY <> Y) then
  1849.                       K := 601;  {Moved}
  1850.                end;
  1851.             end
  1852.             else if ( (Scroll = HorizScroll)
  1853.                       or
  1854.                       (Scroll = BothScroll)
  1855.                     )
  1856.                  and (KX = X+pred(Width)) then
  1857.             begin
  1858.                 if KY = succ(Y) then
  1859.                    K := 610
  1860.                 else if KY =  Y + depth - 2  then
  1861.                    K := 611
  1862.                 else if  (KY > Y+1)
  1863.                    and (KY < Y + depth -2) then {scroll bar}
  1864.                    begin
  1865.                       {adjust X to represent no of characters down scroll bar}
  1866.                       {adjust Y to return total length of scroll bar}
  1867.                       K := 614;
  1868.                       KX := KY - succ(Y);
  1869.                       KY := depth - 2;
  1870.                    end;
  1871.             end
  1872.             else  if ( (Scroll = VertScroll)
  1873.                        or
  1874.                        (Scroll = BothScroll)
  1875.                     )
  1876.                   and (KY = Y+pred(depth)) then
  1877.             begin
  1878.                if KX = succ(X) then
  1879.                   K := 612
  1880.                else if KX = X + width - 2 then
  1881.                   K := 613
  1882.                else if  (KX > succ(X))
  1883.                   and (KX < X + width - 2) then
  1884.                   begin
  1885.                      K := 615;
  1886.                      KX := KX - succ(X);
  1887.                      KY := width - 2;
  1888.                   end;
  1889.             end;
  1890.          end
  1891.          else if (K = 540) and (KY = Y) and (KX >= X) and (KX <= X + pred(Width))
  1892.          and GetBitStatus(WinState,WinAllowStretch) then
  1893.          begin
  1894.             WinToggleZoom;
  1895.             K := 602;
  1896.          end;
  1897.       end;
  1898. end; {WinProcessKey}
  1899.  
  1900.                    {***********************************}
  1901.                    {**  Message Displaying Routines  **}
  1902.                    {***********************************}
  1903.  
  1904. procedure TempMessageCh(X,Y,FB:integer;St:strscreen;var Ch:char);
  1905. {Retained for backward compatibility with TTT5 -  use Prompt procedures}
  1906. var
  1907.  CX,CY,CT,CB,I,locC:integer;
  1908.  SavedLine : array[1..160] of byte;
  1909. begin
  1910.     PartSave(X,Y,pred(X)+length(St),Y,SavedLine);
  1911.     WriteAT(X,Y,FB,St);
  1912.     GetInput;
  1913.     if KeyVars.LastKey <= 255 then
  1914.        Ch := chr(KeyVars.LastKey)
  1915.     else
  1916.        Ch := #0;
  1917.     PartRestore(X,Y,pred(X)+length(St),Y,SavedLine);
  1918. end; {TempMessageCh}
  1919.  
  1920. procedure TempMessage(X,Y,FB:integer;St:strscreen);
  1921. {Retained for backward compatibility with TTT5 -  use Prompt procedures}
  1922. var Ch : char;
  1923. begin
  1924.     TempMessageCH(X,Y,FB,ST,Ch);
  1925. end; {TempMessage}
  1926.  
  1927. procedure TempMessageBoxCh(X1,Y1,FB,BoxType:integer;St:strscreen;var Ch:char);
  1928. {Retained for backward compatibility with TTT5 -  use Prompt procedures}
  1929. begin
  1930.    MkWin(X1,Y1,succ(X1)+length(St),Y1+2,FB,Boxtype);
  1931.    WriteAt(succ(X1),Succ(Y1),FB,St);
  1932.    GetInput;
  1933.    if KeyVars.LastKey <= 255 then
  1934.       Ch := chr(KeyVars.LastKey)
  1935.    else
  1936.       Ch := #0;
  1937.    Rmwin;
  1938. end; {TempMessageBoxCh}
  1939.  
  1940. procedure TempMessageBox(X1,Y1,FB,BoxType:integer;St:strscreen);
  1941. var Ch : char;
  1942. begin
  1943.     TempMessageBoxCh(X1,Y1,FB,Boxtype,St,Ch);
  1944. end; {TempMessageBox}
  1945.  
  1946. function WinGlobalX(WinId:integer;X1:byte):byte;
  1947. {}
  1948. var
  1949.    Temp: WStructurePtr;
  1950. begin
  1951.    if WinID = 0 then
  1952.       Temp := LastWinInChain
  1953.    else
  1954.       Temp := WinPtr(WinId);
  1955.    if Temp <> nil then
  1956.    begin
  1957.       if X1 + pred(Temp^.X) + pred(Temp^.WinX1) < 0 then
  1958.          WinGlobalX := 0
  1959.       else
  1960.          WinGlobalX := X1 + pred(Temp^.X) + pred(Temp^.WinX1)
  1961.    end
  1962.    else
  1963.       WinGlobalX := X1;
  1964. end; {WinGlobalX}
  1965.  
  1966. function WinLocalX(WinId:integer;X1:byte):byte;
  1967. {Converts a full screen X coord to the coord with the window. If the X1 value
  1968.  does not fall within the window a zero is returned}
  1969. var
  1970.    Temp: WStructurePtr;
  1971. begin
  1972.    if WinID = 0 then
  1973.       Temp := LastWinInChain
  1974.    else
  1975.       Temp := WinPtr(WinId);
  1976.    if (Temp = nil)
  1977.    or (X1 < Temp^.X)
  1978.    or (X1 > Temp^.X + pred(Temp^.Width))
  1979.    or (X1 <= pred(Temp^.X) + pred(Temp^.WinX1)) then
  1980.       WinLocalX := 0
  1981.    else
  1982.       WinLocalX := X1 - pred(Temp^.X) - pred(Temp^.WinX1);
  1983. end; {WinLocalX}
  1984.  
  1985. function WinGlobalY(WinId:integer;Y1:byte):byte;
  1986. {}
  1987. var
  1988.    Temp: WStructurePtr;
  1989. begin
  1990.    if WinID = 0 then
  1991.       Temp := LastWinInChain
  1992.    else
  1993.       Temp := WinPtr(WinId);
  1994.    if Temp <> nil then
  1995.    begin
  1996.       if Y1 + pred(Temp^.Y) + pred(Temp^.WinY1) < 0 then
  1997.          WinGlobalY := 0
  1998.       else
  1999.          WinGlobalY := Y1 + pred(Temp^.Y) + pred(Temp^.WinY1)
  2000.    end
  2001.    else
  2002.       WinGlobalY := Y1;
  2003. end; {WinGlobalY}
  2004.  
  2005. function WinLocalY(WinId:integer;Y1:byte):byte;
  2006. {Converts a full screen Y coord to the coord with the window. If the Y1 value
  2007.  does not fall within the window a zero is returned}
  2008. var
  2009.    Temp: WStructurePtr;
  2010. begin
  2011.    if WinID = 0 then
  2012.       Temp := LastWinInChain
  2013.    else
  2014.       Temp := WinPtr(WinId);
  2015.    if (Temp = nil)
  2016.    or (Y1 < Temp^.Y)
  2017.    or (Y1 > Temp^.Y + pred(Temp^.depth)) then
  2018.       WinLocalY := 0
  2019.    else
  2020.       WinLocalY := Y1 - pred(Temp^.Y) - pred(Temp^.WinY1);
  2021. end; {WinLocalY}
  2022.  
  2023.                           {**********************}
  2024.                           {**  Prompt Dialogs  **}
  2025.                           {**********************}
  2026. function PromptEngine(UsingStr: boolean;
  2027.                       pStrLL: StringLLPtr; Tit,Str:string;
  2028.                       But1,But2,But3:StrButton;
  2029.                       HK1,HK2,HK3,Default:word;
  2030.                       WaitTime:longint; EscBut:byte): byte;
  2031. {Central function which displays a modal window and waits for
  2032.  the user to select one of up to three buttons}
  2033. const
  2034.    XGap = 3;
  2035.    YGap = 5;
  2036.    BGap = 5;
  2037. var
  2038.    {window and misc vars}
  2039.    X1,Y1,X2,Y2,W,BW,D,I,P: integer;
  2040.    Handle:integer;
  2041.    StartMemBuffer: longint;
  2042.    X,Y:byte;
  2043.    FirstKey: boolean;
  2044.    {buttonVars}
  2045.    Buts: ThreeButs;
  2046.    ActiveButton: byte;
  2047.    ClickedButton: byte;
  2048.    ButtonCount: byte;
  2049.    ButtonWasDown: boolean;
  2050.    {mouse related vars}
  2051.    MX,MY: byte;
  2052.    L,C,R,
  2053.    Finished,
  2054.    MVisible: boolean;
  2055.  
  2056.    procedure WriteButton(ButID:byte; Down,Force: boolean);
  2057.    {if Force is true the button will be redisplayed, even if the
  2058.     button state has not changed}
  2059.    begin
  2060.       if Force or (Down <> ButtonWasDown) then
  2061.          with Buts[ButID] do
  2062.          begin
  2063.             if Down then
  2064.                DrawButtonDown(X1,X2,Y2,Tint[PromptButtonHiHot],Tint[PromptButtonHi],
  2065.                Buts[ButID].ButtonFace)
  2066.             else
  2067.                if (ButID = ActiveButton) and (ButtonCount > 1) then
  2068.                   DrawButton(X1,X2,Y2,Tint[PromptButtonHiHot],Tint[PromptButtonHi],
  2069.                   Buts[ButID].ButtonFace)
  2070.                else
  2071.                   DrawButton(X1,X2,Y2,Tint[PromptButtonNormHot],Tint[PromptButtonNorm],
  2072.                   Buts[ButID].ButtonFace);
  2073.             ButtonWasDown := Down;
  2074.             if ButID = ActiveButton then
  2075.                GotoXY(X1+(X2 - X1) div 2 + ord(Down),Y2);
  2076.             WinDrawTop;
  2077.          end;
  2078.    end; {WriteButton}
  2079.  
  2080.    procedure SetButtonDetails;
  2081.    {}
  2082.    var I: integer;
  2083.    begin
  2084.       if But1 = '' then
  2085.          Buts[1].ButtonFace := '  ~O~K  '
  2086.       else
  2087.          Buts[1].ButtonFace := But1;
  2088.       Buts[2].Buttonface := But2;
  2089.       Buts[3].Buttonface := But3;
  2090.       {set X2 to width}
  2091.       for I := 1 to 3 do
  2092.          Buts[I].X2 := length(strip('A',HiMarker,Buts[I].ButtonFace));
  2093.       BW :=  Buts[1].X2
  2094.            + Buts[2].X2 + ord(Buts[2].X2>0) * BGAP
  2095.            + Buts[3].X2 + ord(Buts[3].X2>0) * BGAP;
  2096.       {see if the width of the buttons exceeds the widest line}
  2097.       if BW > W then
  2098.         W := BW;
  2099.    end; { SetButtonDetails }
  2100.  
  2101.    procedure PositionButtons;
  2102.    {Sets the button coordinates - at this point X1 contains the button width}
  2103.    var I: integer;
  2104.    begin
  2105.       Buts[1].X1 := (X2 - X1 - BW) div 2;
  2106.       Buts[1].X2 := Buts[1].X1 + pred(Buts[1].X2);
  2107.       for I := 2 to ButtonCount do
  2108.          if Buts[I].X2 > 0 then
  2109.          begin
  2110.             Buts[I].X1 := Buts[pred(I)].X2 + Bgap;
  2111.             Buts[I].X2 := Buts[I].X1 + pred(Buts[I].X2);
  2112.          end;
  2113.    end; { PositionButtons }
  2114.  
  2115.    function WhichButton(X:byte): byte;
  2116.    {Returns the ID of the button or zero if X doesn't fall on a button}
  2117.    begin
  2118.       if (X >= Buts[1].X1) and (X <= Buts[1].X2) then
  2119.          WhichButton := 1
  2120.       else if (ButtonCount > 1) and (X >= Buts[2].X1) and (X <= Buts[2].X2) then
  2121.          WhichButton := 2
  2122.       else if (ButtonCount = 3) and (X >= Buts[3].X1) and (X <= Buts[3].X2) then
  2123.          WhichButton := 3
  2124.       else
  2125.          WhichButton := 0;
  2126.    end; { WhichButton }
  2127.  
  2128.    function WhichHotkey(K:word): byte;
  2129.    {Converts character to uppercase and then compares to hot keys}
  2130.    begin
  2131.       if K = 0 then
  2132.          WhichHotkey := 0
  2133.       else
  2134.       begin
  2135.          if (K > 32) and (K <= 255) then
  2136.            K := ord(GetUpcase(chr(K)));
  2137.          if (K = HK1) then
  2138.             WhichHotkey := 1
  2139.          else if (K = HK2) and (ButtonCount > 1) then
  2140.             WhichHotkey := 2
  2141.          else if (K = HK3) and (ButtonCount = 3) then
  2142.             WhichHotkey := 3
  2143.          else
  2144.             WhichHotkey := 0;
  2145.       end;
  2146.    end; { WhichHotkey }
  2147.  
  2148.    procedure ActivateButton(NewID:byte);
  2149.    {}
  2150.    var OldBut: byte;
  2151.    begin
  2152.       if NewID <> ActiveButton then
  2153.       begin
  2154.          OldBut := ActiveButton;
  2155.          ActiveButton := 0;
  2156.          WriteButton(OldBut,false,true);
  2157.          ActiveButton := NewId;
  2158.          WriteButton(OldBut,false,true);
  2159.       end;
  2160.    end; { ActivateButton }
  2161.  
  2162.    procedure PWrite(X,Y:byte; S:string);
  2163.    {}
  2164.    begin
  2165.       if S[1] = '^' then
  2166.          WriteHiCenter(Y,Tint[PromptBodyHi],Tint[PromptBody],copy(S,2,255))
  2167.       else
  2168.          WriteHi(X,Y,Tint[PromptBodyHi],Tint[PromptBody],S);
  2169.    end; { PWrite }
  2170.  
  2171.    procedure WriteTheMessage;
  2172.    {}
  2173.    var I: integer;
  2174.    begin
  2175.       if D = 1 then
  2176.          PWrite(succ(XGap),2,Str)
  2177.       else
  2178.       begin
  2179.          for I := 1 to D do
  2180.          begin
  2181.             if UsingStr then
  2182.             begin
  2183.             P := pos(StrVars.LineBreak,Str);
  2184.             if P = 0 then
  2185.                PWrite(succ(XGap),succ(I),Str)
  2186.             else
  2187.                PWrite(succ(XGap),succ(I),copy(Str,1,pred(P)));
  2188.             delete(Str,1,P);
  2189.             end
  2190.             else
  2191.                PWrite(succ(XGap),succ(I),StrLLGetStr(pStrLL^,I));
  2192.          end;
  2193.       end;
  2194.  
  2195.    end; {WriteTheMessage}
  2196.  
  2197. begin
  2198.    StartMemBuffer := MiscVars.GoldMemBuffer; { use Total heap }
  2199.    MiscVars.GoldMemBuffer := 0;
  2200.    if UsingStr then
  2201.       W := WidestLine(Str)
  2202.    else
  2203.       W := StrLLWidestLine(pStrLL^);
  2204.    if W < length(Tit) then
  2205.       W := length(Tit);
  2206.    SetButtonDetails;
  2207.    if W + 2*succ(XGap) > HardVars.Width then
  2208.       W := HardVars.Width - 2*succ(XGap);
  2209.    if UsingStr then
  2210.       D := LineCount(Str)
  2211.    else
  2212.       D := pStrLL^.TotalNodes;
  2213.    if D + YGap > HardVars.Depth then
  2214.       D := HardVars.Depth - YGap;
  2215.    X1 := succ((HardVars.Width - W - 2*succ(XGap)) div 2);
  2216.    X2 := X1 + W + 2*succ(XGap);
  2217.    Y1 := succ((HardVars.Depth - D - YGap) div 2);
  2218.    Y2 := Y1 + D + YGap;
  2219.    Handle := WinCreate(X1,Y1,X2,Y2,WinVars.PromptStyle);
  2220.    WinSetType(Handle,WMoveNoClose);
  2221.    WinSetTitle(Handle,Tit);
  2222.    WinSetColor(Handle,WinBorder3DOut,Tint[PromptBorder1]);
  2223.    WinSetColor(Handle,WinBorder3DIn,Tint[PromptBorder2]);
  2224.    WinSetColor(Handle,WinBorder,Tint[PromptBorder1]);
  2225.    WinSetColor(Handle,WinBody,Tint[PromptBody]);
  2226.    WinSetColor(Handle,WinTitle,Tint[PromptTitle]);
  2227.    WinSetColor(Handle,WinCaption,Tint[PromptTitle]);
  2228.    WinSetShowNum(Handle,false);
  2229.    MVisible := KeyVars.MouseVisible;
  2230.    if not MVisible then
  2231.       MouseShow(true);
  2232.    WinDisplay(Handle);
  2233.    WriteTheMessage;
  2234.    {set coordinates of the button locations}
  2235.    ActiveButton := Default;
  2236.    if Buts[2].X2 = 0 then {ignore Button 3 if button 2 is nul}
  2237.       ButtonCount := 1
  2238.    else
  2239.       ButtonCount := 2 + ord(Buts[3].X2 > 0);
  2240.    if (ActiveButton < 1) or (ActiveButton > ButtonCount) then
  2241.       ActiveButton := 1;
  2242.    PositionButtons;
  2243.    Y2 := Y2-Y1-2;         {adjust Y2 to be button line}
  2244.    for I := 1 to ButtonCount do
  2245.       WriteButton(I,false,true);
  2246.    {some key processing stuff}
  2247.    Finished := false;
  2248.    MVisible := KeyVars.MouseVisible;
  2249.    (*
  2250.    WinDrawAll;
  2251.    *)
  2252.    WinDrawTop;
  2253.    if not MVisible then
  2254.       MouseShow(true);
  2255.    FirstKey := true;
  2256.    repeat
  2257.       GetInputWait(WaitTime);
  2258.       with KeyVars do
  2259.         if IsWinKey(LastKey,LastX,LastY) then
  2260.            WinProcessKey(LastKey,LastX,LastY);
  2261.         case KeyVars.Lastkey of
  2262.            0: begin
  2263.                if (WaitTime > 0) and FirstKey then {time expired}
  2264.                begin
  2265.                   WinDispose(Handle);
  2266.                   Finished := true;
  2267.                   ActiveButton := 0;
  2268.                end;
  2269.            end;
  2270.            600: begin {close icon}
  2271.                WinDispose(Handle);
  2272.                Finished := true;
  2273.                MouseRelease;
  2274.            end;
  2275.            601: begin  {window moved, but nothing to do}
  2276.            end;
  2277.            9,            {Tab, Right, Down}
  2278.            336,
  2279.            333: if ButtonCount > 1 then begin  {move right a button}
  2280.                if ActiveButton = ButtonCount then
  2281.                   ActivateButton(1)
  2282.                else
  2283.                   ActivateButton(succ(ActiveButton));
  2284.                WriteButton(ActiveButton,false,true);
  2285.            end;
  2286.            271,       {shift-Tab, up, left}
  2287.            331,
  2288.            328: if ButtonCount > 1 then begin  {move left a button}
  2289.                if ActiveButton = 1 then
  2290.                   ActivateButton(ButtonCount)
  2291.                else
  2292.                   ActivateButton(pred(ActiveButton));
  2293.                WriteButton(ActiveButton,false,true);
  2294.            end;
  2295.            13 :begin
  2296.               Finished := true;
  2297.               WinDispose(Handle);
  2298.            end;
  2299.            27: begin
  2300.               if EscBut <> 0 then
  2301.               begin
  2302.                  ActiveButton := EscBut;
  2303.                  Finished := true;
  2304.                  WinDispose(Handle);
  2305.               end;
  2306.            end;
  2307.            500: begin {left mouse down - animate the button}
  2308.               with KeyVars do
  2309.               begin
  2310.                  MX := WinLocalX(Handle,LastX);
  2311.                  MY := WinLocalY(Handle,LastY);
  2312.                  if (MY = Y2) then  {on button line}
  2313.                  begin
  2314.                     ClickedButton := WhichButton(MX);
  2315.                     if ClickedButton = 0 then
  2316.                        MouseRelease
  2317.                     else
  2318.                     begin
  2319.                        if ClickedButton <> ActiveButton then
  2320.                           ActivateButton(ClickedButton);
  2321.                        with Buts[ActiveButton] do
  2322.                        begin
  2323.                           repeat
  2324.                              MouseStatus(L,C,R,X,Y);
  2325.                              X := WinLocalX(Handle,X);
  2326.                              Y := WinLocalY(Handle,Y);
  2327.                              if L and ( (Y <> Y2) or (X < X1) or (X > X2+ord(ButtonWasDown))) then
  2328.                                 WriteButton(ActiveButton,false,false)
  2329.                              else
  2330.                                 WriteButton(ActiveButton,true,false);
  2331.                           until not L;
  2332.                           if (X >= X1) and (X <= X2+ord(ButtonWasDown)) and (Y = Y2) then
  2333.                           begin
  2334.                              Finished := true;
  2335.                              WinDispose(Handle);
  2336.                           end
  2337.                           else
  2338.                              WriteButton(ActiveButton,false,false);
  2339.                        end; {with}
  2340.                     end;
  2341.                  end
  2342.                  else
  2343.                     MouseRelease; {clicked away from buttons}
  2344.               end;
  2345.            end;  {case for 500}
  2346.            else begin
  2347.                ClickedButton := WhichHotKey(KeyVars.Lastkey);
  2348.                if ClickedButton <> 0 then
  2349.                begin
  2350.                   ActivateButton(ClickedButton);
  2351.                   Finished := true;
  2352.                   WinDispose(Handle);
  2353.                end;
  2354.            end;
  2355.         end; {case}
  2356.         FirstKey := false;
  2357.    until Finished;
  2358.    PromptEngine := ActiveButton;
  2359.    if not MVisible then
  2360.       MouseShow(false);
  2361.    MiscVars.GoldMemBuffer := StartMemBuffer;
  2362. end; { PromptEngine }
  2363.  
  2364. function PromptCustom(Tit,Str:string; But1,But2,But3:StrButton; HK1,HK2,HK3,Default:word; WaitTime:longint): byte;
  2365. {}
  2366. begin
  2367.    PromptCustom := PromptEngine(true,nil,Tit,Str,But1,But2,But3,HK1,HK2,HK3,Default,WaitTime,0);
  2368. end; { PromptCustom }
  2369.  
  2370. function PromptCustomStrLL(Tit:string; StrLL:StringLL; But1,But2,But3:StrButton;
  2371.                       HK1,HK2,HK3,Default:word; WaitTime:longint): byte;
  2372. {}
  2373. begin
  2374.    PromptCustomStrLL := PromptEngine(false,@StrLL,Tit,'',But1,But2,But3,HK1,HK2,HK3,Default,WaitTime,0);
  2375. end; { PromptCustomStrLL }
  2376.  
  2377. procedure PromptOK(Tit,Str:string);
  2378. {Displays a window with a short message and an OK button - the |
  2379.  character is used to split the lines}
  2380. begin
  2381.    with WinVars do
  2382.       if PromptEngine(true,nil,Tit,Str,OKbutStr,'','',OKHotKey,0,0,1,0,1) = 1 then;
  2383. end; { PromptOK }
  2384.  
  2385. procedure PromptOKStrLL(Tit:string;StrLL:StringLL);
  2386. {Displays a window with a short message and an OK button - the |
  2387.  character is used to split the lines}
  2388. begin
  2389.    with WinVars do
  2390.       if PromptEngine(false,@StrLL,Tit,'',OKbutStr,'','',OKHotKey,0,0,1,0,1) = 1 then;
  2391. end; { PromptOKStrLL }
  2392.  
  2393. function PromptYesNo(Tit,Str:string): byte;
  2394. {}
  2395. begin
  2396.    with WinVars do
  2397.       PromptYesNo := PromptEngine(true,nil,Tit,Str,YesButStr,NoButStr,'',YesHotKey,NoHotKey,0,1,0,2);
  2398. end; { PromptYesNo }
  2399.  
  2400. function PromptYesNoStrLL(Tit:string;StrLL:StringLL): byte;
  2401. {}
  2402. begin
  2403.    with WinVars do
  2404.       PromptYesNoStrLL := PromptEngine(false,@StrLL,Tit,'',YesButStr,NoButStr,'',YesHotKey,NoHotKey,0,1,0,2);
  2405. end; { PromptYesNoStrLL }
  2406.  
  2407. function PromptOKCancel(Tit,Str:string): byte;
  2408. {}
  2409. begin
  2410.    with WinVars do
  2411.       PromptOKCancel := PromptEngine(true,nil,Tit,Str,OKbutStr,CancelButStr,'',OKHotkey,CancelHotkey,0,1,0,2);
  2412. end; { PromptOKCancel }
  2413.  
  2414. function PromptOKCancelStrLL(Tit:string;StrLL:StringLL): byte;
  2415. {}
  2416. begin
  2417.    with WinVars do
  2418.       PromptOKCancelStrLL := PromptEngine(false,@StrLL,Tit,'',OKbutStr,
  2419.                                           CancelButStr,'',OKHotkey,CancelHotkey,0,1,0,2);
  2420. end; { PromptOKCancelStrLL }
  2421.  
  2422.                         {*************************}
  2423.                         {**  DRAGGING ROUTINES  **}
  2424.                         {*************************}
  2425.  
  2426. procedure DragItem(var X1,Y1,X2,Y2:byte;DragAttr:byte;UsingMouse:boolean;Fillch:char;FillAttr:byte);
  2427. var
  2428.    Left,Center,Right : boolean;
  2429.    OldX,OldY,
  2430.    X,Y : Byte;
  2431.    DeltaX, DeltaY : shortint;
  2432.    ScrPtr,
  2433.    OldPtr,
  2434.    SmartWinImagePtr : pointer;
  2435.    Wid: word;
  2436.    W,D: byte;
  2437.    Boundary,
  2438.    OldLocation : gCoords;
  2439.  
  2440.   procedure CaptureMoveableArea;
  2441.   {saves image of window}
  2442.   var I : integer;
  2443.   begin
  2444.      getmem(SmartWinImagePtr,W*D*2);
  2445.      PartSave(X1,Y1,X2,Y2,SmartWinImagePtr^);
  2446.   end; {CaptureMoveableArea}
  2447.  
  2448.   procedure RestoreSmartWin;
  2449.   {}
  2450.   begin
  2451.      PartRestore(X1,Y1,X2,Y2,SmartWinImagePtr^);
  2452.   end; {RestoreSmartWin}
  2453.  
  2454.   procedure DisposeSmartWin;
  2455.   {}
  2456.   begin
  2457.      freemem(SmartWinImagePtr,W*D*2);
  2458.   end; {DisposeSmartWin}
  2459.  
  2460.   procedure FastRestore(X1,Y1,X2,Y2:byte);
  2461.   {}
  2462.   var
  2463.      I,W : integer;
  2464.      ScreenAdr: integer;
  2465.   begin
  2466.      if (X1 > X2) or (Y1 > Y2) then
  2467.         exit;
  2468.      W := succ(X2 - X1);
  2469.      MoveToScreen(X1,Y1,X2,Y2,HardVars.Width,OldPtr^,X1,Y1,HardVars.Width,ScrPtr^);
  2470.   end; {FastRestore}
  2471.  
  2472. begin
  2473.    Boundary.X1 := 1;
  2474.    Boundary.Y1 := 1;
  2475.    Boundary.X2 := 80;
  2476.    Boundary.Y2 := 25;
  2477.    W := succ(X2 - X1);
  2478.    D := succ(Y2 - Y1);
  2479.    if GoldMaxAvail < W*D*2 * HardVars.Width*HardVars.Depth*2 then
  2480.    begin
  2481.       Beep;
  2482.       exit;
  2483.    end;
  2484.    CaptureMoveableArea;
  2485.    if DragAttr <> 0 then
  2486.    begin
  2487.       with Boundary do
  2488.          Attrib(X1,Y1,X2,Y2,DragAttr);
  2489.       RestoreSmartWin;
  2490.    end;
  2491.    SaveScreen(InternalScreen1);
  2492.    if FillCh <> #0 then
  2493.    begin
  2494.       ActivateVirtualScreen(InternalScreen1);
  2495.       PartClear(X1,Y1,X2,Y2,FillAttr,FillCh);
  2496.       ActivateVisibleScreen;
  2497.    end;
  2498.    ScrPtr :=  HardVars.ScreenPtr;
  2499.    OldPtr := FastVars.Screen[InternalScreen1]^.ScreenPtr;
  2500.    Wid := HardVars.Width*2;
  2501.    if UsingMouse then
  2502.       MouseStatus(Left,Center,Right,OldX,OldY);
  2503.    repeat
  2504.       if UsingMouse then
  2505.       begin
  2506.          MouseShow(true);
  2507.          MouseStatus(Left,Center,Right,X,Y);
  2508.       end
  2509.       else
  2510.       begin
  2511.          OldX := 20;
  2512.          OldY := 20;
  2513.          Y := 20;
  2514.          X := 20;
  2515.          GetInput;
  2516.          case KeyVars.LastKey of
  2517.             328: dec(Y); {up}
  2518.             336: inc(Y); {down}
  2519.             333: inc(X); {right}
  2520.             331: dec(X); {left}
  2521.          end; {case}
  2522.          Left := true;
  2523.       end;
  2524.       if Left and ( (X <> OldX) or (Y <> OldY) ) then  {move window}
  2525.       begin
  2526.          OldLocation.X1 := X1;
  2527.          OldLocation.Y1 := Y1;
  2528.          OldLocation.X2 := X2;
  2529.          OldLocation.Y2 := Y2;
  2530.          if (X <> OldX) then
  2531.          begin
  2532.             DeltaX := X - OldX;
  2533.             if  (DeltaX + X1 >= Boundary.X1)
  2534.             and (DeltaX + X2 <= Boundary.X2) then
  2535.             begin
  2536.                inc(X1,DeltaX);
  2537.                inc(X2,DeltaX);
  2538.             end
  2539.             else
  2540.               DeltaX := 0;
  2541.          end
  2542.          else
  2543.             DeltaX := 0;
  2544.          if (Y <> OldY) then
  2545.          begin
  2546.             DeltaY := Y - OldY;
  2547.             if  (DeltaY + Y1 >= Boundary.Y1)
  2548.             and (DeltaY + Y2 <= Boundary.Y2) then
  2549.             begin
  2550.                inc(Y1, DeltaY);
  2551.                inc(Y2, DeltaY);
  2552.             end
  2553.             else
  2554.               DeltaY := 0;
  2555.          end
  2556.          else
  2557.             DeltaY := 0;
  2558.          MouseShow(false);
  2559.          RestoreSmartWin;
  2560.          if DeltaX > 0 then {Viewport moved right}
  2561.             FastRestore(OldLocation.X1,Y1,pred(X1),Y2)
  2562.          else if DeltaX < 0 then {viewport moved left}
  2563.             FastRestore(succ(X2),Y1,OldLocation.X2,Y2);
  2564.          if DeltaY > 0 then {Viewport moved down}
  2565.             FastRestore(OldLocation.X1,OldLocation.Y1,X2,pred(Y1))
  2566.          else if deltaY < 0 then {Viewport moved up}
  2567.             FastRestore(OldLocation.X1,succ(Y2),X2,OldLocation.Y2);
  2568.          if DeltaX < 0 then    {moved left}
  2569.          begin
  2570.              if (DeltaY > 0) then
  2571.                 FastRestore(succ(X1),OldLocation.Y1,Oldlocation.X2,pred(Y1))
  2572.              else
  2573.                 FastRestore(succ(X2),succ(Y2),Oldlocation.X2,OldLocation.Y2);
  2574.          end;
  2575.          OldX := X;
  2576.          OldY := Y;
  2577.          {Mouse.Move(X,Y);}
  2578.       end; {if}
  2579.    until (UsingMouse and (Left = false))
  2580.       or (((KeyVars.LastKey = 13)
  2581.           or
  2582.           (KeyVars.LastKey = 27)) and (UsingMouse = false)
  2583.          );
  2584.    DisposeScreen(InternalScreen1);
  2585.    DisposeSmartWin;
  2586. end; {DragItem}
  2587.  
  2588.               {*********************************************}
  2589.               {**  U N I T   I N I T I A L I Z A T I O N  **}
  2590.               {*********************************************}
  2591.  
  2592. procedure WinDefaultSettings;
  2593. {}
  2594. begin
  2595.    with WinVars do
  2596.    begin
  2597.       RotateKey := 320;       {F6}
  2598.       MoveKey := 354;         {Ctrl-F5}
  2599.       ZoomKey := 319;         {F5}
  2600.       StretchKey := 364;      {Alt-F5}
  2601.       CloseKey := 362;        {Alt-F3}
  2602.       {defaults for new windows}
  2603.       WinState := 0; {set everything false}
  2604.       SetBitStatus(WinState,WinConfine,true); {window write limitations are active}
  2605.       (* DEVELOPER NOTE: Enable one or more of the following
  2606.                          to change defaults
  2607.       SetBitStatus(WinState,WinAllowMove,true);
  2608.       SetBitStatus(WinState,WinAllowClose,true);
  2609.       SetBitStatus(WinState,WinAllowStretch,true);
  2610.       SetBitStatus(WinState,WinShowNum,true);
  2611.       *)
  2612.       Scroll := NoScroll;
  2613.       PromptStyle := 7;
  2614.       DesktopFadeStyle := 1;
  2615.       DesktopFocusStyle := 2;
  2616.       DesktopNums := WShowNumbers;
  2617.       DesktopCascadeNew := true;
  2618.       MinWidth := 12;
  2619.       MinDepth := 7;
  2620.       with Boundary do
  2621.       begin
  2622.          X1 := 1;
  2623.          Y1 := 1;
  2624.          X2 := HardVars.Width;
  2625.          Y2 := HardVars.Depth;
  2626.       end;
  2627.       WinCloseChar := '■';
  2628.       WinCloseCharDown := '';
  2629.       WinZoomMaxChar := '';
  2630.       WinZoomBackChar := '';
  2631.       {move message}
  2632.       WinMoveMsgPart1 := 'Move window using arrow keys';
  2633.       WinMoveMsgPart2 := 'Press ~Enter~ when done';
  2634.       {buttons}
  2635.       OKButStr := '   ~O~K   ';
  2636.       OKHotKey := 280;          { Alt+O }
  2637.       CancelButStr := ' ~C~ancel ';
  2638.       CancelHotKey := 302;      { Alt+C }
  2639.       YesButStr := '   ~Y~es   ';
  2640.       YesHotKey := 277;         {Alt-Y}
  2641.       NoButStr := '   ~N~o   ';
  2642.       NoHotKey := 305;          {Alt-N}
  2643.       HelpButStr := '  ~H~elp  ';
  2644.       HelpHotKey := 291;
  2645.    end;
  2646. end; {WinDefaultSettings}
  2647.  
  2648. procedure GoldWinInit;
  2649. {}
  2650. begin
  2651.    with WinVars do
  2652.    begin
  2653.       LastECode := 0;
  2654.       FirstWin := nil;
  2655.       TopWin := nil;
  2656.       EMsgFunc := WinEMsg;
  2657.    end;
  2658.    WinDefaultSettings;
  2659. end; {GoldWinInit}
  2660.  
  2661. begin
  2662.    GoldWinInit;
  2663. end.
  2664.